home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 501-525 / disk_503 / pcq / pcq12a.lzh / Pascal.DOC < prev    next >
Text File  |  1991-06-09  |  149KB  |  3,690 lines

  1. ===================================================================
  2.  
  3.                       PCQ Pascal version 1.2
  4.                  A Pascal compiler for the Amiga
  5.                          by Patrick Quaid
  6.  
  7.  
  8. ===================================================================
  9.  
  10. PCQ Pascal is a simple Pascal compiler for the Amiga personal
  11. computer.  It is freely distributable, which means that I retain
  12. the copyright to the compiler, the runtime library, the source of
  13. the compiler and runtime library, as well as this documentation.
  14. It can all be freely distributed as long as you don't charge too
  15. much (see the last section for more information).  To summarize
  16. the compiler's features:
  17.  
  18. The bad:
  19.  
  20.     o  The compiler doesn't support sets.
  21.     o  It isn't compatible with Turbo Pascal, although it's getting
  22.            closer.
  23.     o  Some things are slightly different from Standard Pascal.
  24.     o  The compiler gets knocked for a loop by most errors.
  25.  
  26. The good:
  27.  
  28.     o  It works.
  29.     o  It supports include files.
  30.     o  It allows for separate compilation, although you have to
  31.            do the checking (this isn't Modula-2, after all).
  32.     o  It supports records, enumerated types, pointers, arrays,
  33.            and C strings.
  34.     o  Type casts as found in Modula-2 is supported.  In other
  35.            words, something like "Byte('d')" is legal.
  36.     o  Several features from Turbo and Quick Pascal, such as Exit
  37.            procedures, operators such as Shl and Shr, and typed
  38.            constants, are supported.
  39.     o  You can have as many const, var, type, procedure and
  40.            function blocks as you want, in any order.
  41.     o  It's free!
  42.  
  43.  
  44.  
  45.  
  46.  
  47. ===================================================================
  48.  
  49.                         Table of Contents
  50.  
  51. ===================================================================
  52.  
  53.  
  54. This manual is designed to be read with a file reader or text
  55. editor, so this table of contents is based on line numbers rather
  56. than page numbers.  See the last section about getting a
  57. page-oriented version.
  58.  
  59.  
  60.         Section                                   Line Number
  61.      -----------------------------------------------------------
  62.  
  63.         Installing PCQ .............................  160
  64.             What have I got here? ..................  164
  65.             How do I make a work disk? .............  208
  66.         Compiling a program ........................  377
  67.         Incompatibilities ..........................  513
  68.  
  69.         PCQ Programs ...............................  582
  70.         Reserved Words .............................  597
  71.         Pascal Program Structure ...................  626
  72.  
  73.         Type Declarations ..........................  699
  74.             Numeric Types ..........................  733
  75.             Other Ordinal Types ....................  766
  76.             Pointer Types ..........................  792
  77.             File Types .............................  809
  78.             Type Compatibility .....................  832
  79.  
  80.         Constant Declarations ......................  861
  81.             Typed Constants ........................  897
  82.             Standard Constants .....................  972
  83.  
  84.         Variable Declarations ...................... 1016
  85.             Standard Variables ..................... 1049
  86.  
  87.         Procedure & Function Declarations .......... 1102
  88.             Parameter Passing ...................... 1133
  89.             Forward Procedures & Functions ......... 1177
  90.             External Routines ...................... 1203
  91.             Standard Procedures .................... 1226
  92.             Standard Functions ..................... 1370
  93.  
  94.         Label Declarations ......................... 1544
  95.  
  96.         Expressions ................................ 1568
  97.             Evaluation Order & Short Circuits ...... 1734
  98.             Constant Expressions ................... 1789
  99.             Variable References .................... 1799
  100.  
  101.         Statements ................................. 1837
  102.             If Statements .......................... 1857
  103.             While Statements ....................... 1882
  104.             Repeat Statements ...................... 1898
  105.             For Statements ......................... 1917
  106.             Case Statements ........................ 1961
  107.             With Statements ........................ 1994
  108.             Compound Statements .................... 2030
  109.             Assignment Statements .................. 2046
  110.             Procedure Calls ........................ 2059
  111.             Return Statements ...,.................. 2085
  112.             Goto Statements ........................ 2105
  113.  
  114.         Input/Output ............................... 2137
  115.             Pascal IO .............................. 2142
  116.             Text and Typed Files ................... 2180
  117.             Opening Files .......................... 2230
  118.             Writing to Files ....................... 2324
  119.             Reading from Files ..................... 2391
  120.             File Buffers ........................... 2475
  121.             IO Checking ............................ 2539
  122.             Standard IO ............................ 2566
  123.  
  124.         Strings .................................... 2641
  125.             Allocating String Space ................ 2677
  126.             Using Escape Characters ................ 2724
  127.             StringLib .............................. 2763
  128.  
  129.         Memory Management .......................... 2777
  130.             HeapError .............................. 2813
  131.  
  132.         Exit Procedures ............................ 2847
  133.             Runtime Errors ......................... 2891
  134.  
  135.         Compiler Directives ........................ 2963
  136.  
  137.         Type Casts ................................. 3097
  138.  
  139.         Small Initialization Code .................. 3141
  140.  
  141.         External Files ............................. 3205
  142.  
  143.         Notes to Assembly Programmers .............. 3278
  144.  
  145.         Errors ..................................... 3309
  146.  
  147.         Sources .................................... 3340
  148.  
  149.         Improvements on the Burner ................. 3427
  150.  
  151.         Update History ............................. 3454
  152.  
  153.         Other Notes, Copyright & My Address ........ 3635
  154.  
  155.  
  156.  
  157.  
  158. ===================================================================
  159.  
  160.                           Installing PCQ
  161.  
  162. ===================================================================
  163.  
  164.  What have I got here?
  165. -----------------------
  166.  
  167. What is included in the PCQ distribution depends on where you got
  168. it from.  If you got the disk from me, it most likely includes
  169. everything.  If you downloaded it, it probably does not include
  170. several common files, nor does it include the source for the
  171. compiler or runtime library.  It does, however, contain some
  172. combination of the following:
  173.  
  174.         Pascal          The compiler itself
  175.         Peep            The peephole optimizer
  176.         Pascal.DOC      This documentation file
  177.         Readme.PCQ      A short description of PCQ
  178.         PCQ.lib         The runtime library
  179.         Include.LZH     The include file library, compressed with
  180.                         the LHArc program.
  181.         Examples.LZH    Several example programs, also compressed
  182.                         with LHArc.
  183.         IDList.LZH      A directory for the include files
  184.         Source.LZH      The Pascal source code of the compiler (1)
  185.         Runtime.LZH     The Pascal and assembly source code of
  186.                         PCQ.lib. (1)
  187.  
  188.         A68k            Charlie Gibbs' assembler (2)
  189.         A68k.doc        The documentation for A68k (2)
  190.         A68k2do.txt     Improvements planned for A68k (2)
  191.         History.log     Version-by-version changes of A68k (2)
  192.  
  193.         Blink           The Software Distillery linker (2)
  194.         Blink.doc       The documentation for Blink (2)
  195.  
  196.     (1) Since these files are pretty big, and of interest to very
  197.         few people, I normally only include them by request.  If
  198.         you want them, just send me a disk (see the last section).
  199.     (2) These files are often omitted from the BBS archive version
  200.         of the distribution to cut download times.  They are
  201.         already available on most systems, but if you are
  202.         uploading PCQ to a system, you might want to point out
  203.         that A68k and Blink are also necessary, and verify that
  204.         they are also available.
  205.  
  206.  
  207.  
  208.  How do I make a work disk?
  209. ----------------------------
  210.  
  211. Glad you asked.  The answer is that I don't know.  There are
  212. jillions of different system configurations out there, so I can't
  213. tell you exactly how to set your system up.  But I can give you
  214. some general guidelines.
  215.  
  216. First of all, somewhere in your command path you are going to need
  217. the compiler, assembler, linker, and a text editor.  Normally
  218. these would go in the C:  directory, but if you use the AmigaDOS
  219. PATH command, they can go in any of the path directories.
  220.  
  221. If you don't have a text editor, I heartily recommend CygnusEd
  222. Professional from ASDG.  TxEd is supposed to be about as good, but
  223. I've never used it.  Programmers on a budget can use MEMACS from
  224. the Extras disk, ED from the Workbench disk, or a variety of
  225. freely distributable editors like DME.  ED isn't a great choice,
  226. MEMACS is fair, and from what I hear DME is really good.  Take
  227. your pick.
  228.  
  229. The other file you'll definitely need is the runtime library,
  230. which can go anywhere.  I keep mine in my work directory, but
  231. others like to keep it in their LIBS:  directory.  It's up to you,
  232. but don't forget where you put it.
  233.  
  234. These files are all absolutely necessary for even the simplest
  235. programs.  If you want to use any Amiga routines, or use special
  236. routines from PCQ.lib, you will also need to install the include
  237. file library.  This is where it gets a bit hairy, because the set
  238. of include files is just under 800 disk blocks (a little less than
  239. 400k).  That's half a floppy disk right there.  The size of these
  240. files is going to make it awfully hard to use the complete system
  241. on single drive systems.  If you want to install the Include files
  242. you'll also need to find a copy of LHArc (or one of the compatible
  243. archivers).  LHArc is available on virtually all bulletin boards,
  244. so you shouldn't have much of a problem finding a copy (if you
  245. have not yet done so, do yourself a favor and buy a modem.  It's
  246. the best investment you'll make).
  247.  
  248. So how do we organize all this stuff?  It depends on your system,
  249. of course, but here's a few examples.  If you want to install the
  250. program on a hard drive, you could try the following.  First, copy
  251. Pascal, A68k, and Blink to your C:  directory (also copy a text
  252. editor if one is not already there).  Then create a work
  253. directory.  Copy PCQ.lib to this new directory.  Now make a
  254. subdirectory of your work directory called something like
  255. "Include".  It's actually not necessary that it's a subdirectory,
  256. but it will help you keep your disk structure straight.  Then use
  257. the AmigaDOS ASSIGN command to make an assignment of Include:  to
  258. your new include directory.  Now you want to uncompress the
  259. include file library into your new include directory, with a
  260. command like:
  261.  
  262.         LHArc -x -r x DistributionDisk:Include Include:
  263.  
  264. Use the actual path of the include archive, or course.  Every time
  265. you use the compiler, you should be sure to properly ASSIGN the
  266. Include:  directory - you'll probably want to put that assignment
  267. in the startup-sequence or an initialization script.
  268.  
  269.  
  270. If you have one disk drive, I recommend the following disk
  271. structure.  The problem here is that I don't have a one-drive
  272. system on which to test this, so you may have to adjust it
  273. somewhat.
  274.  
  275.     Root:
  276.         PCQ.lib
  277.         C (dir)
  278.             A68k                             Assign
  279.             Avail                            Blink
  280.             CD                               Copy
  281.             Date                             Delete
  282.             Echo                             Ed
  283.             Else                             EndCLI
  284.             EndIf                            EndSkip
  285.             Execute                          Failat
  286.             If                               Info
  287.             Join                             Lab
  288.             List                             LoadWB
  289.             Makedir                          NewShell
  290.             Pascal                           Path
  291.             Prompt                           Protect
  292.             Quit                             Relabel
  293.             Rename                           Resident
  294.             Run                              SetPatch
  295.             Stack                            Type
  296.         Libs (dir)
  297.             diskfont.library                 icon.library
  298.             mathtrans.library                version.library
  299.         Devs (dir)
  300.             ramdrive.device                  system-configuration
  301.         S (dir)
  302.             Startup-Sequence                 Make
  303.         L (dir)
  304.             Disk-Validator                   Newcon-Handler
  305.             Port-Handler                     Ram-Handler
  306.             Shell-Seg                        
  307.         Include (dir)
  308.             All the include files...
  309.         Trashcan (dir)
  310.  
  311.  
  312.  
  313. To make this sort of disk, first make a copy of a standard
  314. Workbench disk.  Then prune away everything, and I mean
  315. everything, that you don't absolutely need.  You'll note for
  316. example that the list above doesn't even have the serial.device
  317. and the parallel.device, so you can't use your modem or printer.
  318. These sorts of sacrifices will have to be made.  Next, copy
  319. Pascal, A68k and Blink to the :c  directory, then copy Make to the
  320. :s  directory and PCQ.lib to the new disk's root.  Make a new
  321. directory called Include, then CD to it.  Uncompress the Include
  322. file directory by using the following command:
  323.  
  324.     LHArc -x -r x Distribution:Include WorkDisk:Include/
  325.  
  326. Use the actual path for LHArc and the archive itself.  You might
  327. have to run Install on the disk to make it bootable, but you'll
  328. have yourself a barely usable work disk for Pascal.  You will have
  329. virtually no free space, so you'll have to edit and compile files
  330. in RAM:, copying them to a separate disk as often as possible.  It
  331. will be a hard life.  If you are only writing very simple,
  332. standard Pascal programs, which use none of the Amiga's special
  333. features, you can leave out the include directory (thus freeing up
  334. nearly 400k), but you won't be able to create very interesting
  335. programs.  Single drive users probably have several tricks up
  336. their sleeves to get around disk space problems, so if you know of
  337. a better plan, by all means use it.
  338.  
  339. If you have two disks, I would recommend a setup similar to the
  340. single drive system.  Move the include directory to the second
  341. disk, however, and flesh out the system files on the boot disk (so
  342. you can use your printer, especially).  Use the ~400k of free
  343. space on your second drive as your work area.  This is the sort of
  344. setup I used when I originally developed PCQ.
  345.  
  346. If you have lots of RAM (say, a megabyte or more), you might want
  347. to copy some of this stuff into RAM:  or RAD:  to free up work
  348. space.  For example, if you have one megabyte of RAM you might be
  349. able to copy the entire Include directory to the RAM:  disk and
  350. still have enough memory to compile medium sized programs.
  351.  
  352. The one optional part of the system is the peephole optimizer,
  353. Peep.  This program takes the assembly output of the compiler and
  354. makes it somewhat more efficient and slightly smaller.  If you are
  355. compiling on floppy disks you'll probably want to skip it, but if
  356. you are working in RAM or on a hard disk it's doesn't add much to
  357. the compilation time.  Peep should be copied to the same place as
  358. Pascal.
  359.  
  360. However you end up configuring your system, you'll have to
  361. define the Include:  assignment to point to your include file
  362. directory.  This assignment is just the convention I used in the
  363. include files and example programs - it's not part of the compiler
  364. itself, in other words - so if you are willing to modify all the
  365. include files you can use whatever assignment you like.  The only
  366. other assignment of interest is the T:  directory.  This one is
  367. automatically created by AmigaDOS, and since it is used by the
  368. Make script to store intermediate files, assigning it to a RAM:
  369. directory speeds up the whole compilation cycle dramatically.
  370.  
  371.  
  372.  
  373.  
  374.  
  375. ===================================================================
  376.  
  377.                        Compiling a Program
  378.  
  379. ===================================================================
  380.  
  381. Turning a Pascal source file into an executable program is (at
  382. last count) a four step process.  You start off with your source
  383. code (one of the example programs, for example), which probably
  384. ends with ".p".  The first step is to use the compiler to turn
  385. this source file into an equivalent assembly language program.  To
  386. do this, invoke the compiler with the following command format:
  387.  
  388.         Pascal InputPascal OutputAssembly [-q] [-s] [-b]
  389.  
  390. "InputPascal" should be replaced with the complete filename
  391. (including path, if necessary) of your source file, and
  392. "OutputAssembly" is the filename (optionally with a path) of the
  393. assembly language output file.  I normally use the extension
  394. ".asm" on the output file.  The command line arguments can be
  395. placed anywhere on the command line, in upper or lower case, and
  396. have the following meaning:
  397.  
  398.      -q      Run in "quiet" mode, i.e. the compiler does not
  399.              write anything to the screen except error
  400.              messages.  This makes it easier to parse the
  401.              output of the compiler in an ARexx script, for
  402.              example.
  403.  
  404.      -s      Small initialization.  Small programs use a
  405.              different initialization routine that does not
  406.              have all the overhead of the standard routine,
  407.              but it means that you will not be able to use any
  408.              Pascal IO (e.g Writeln(), Readln(), etc).
  409.  
  410.      -b      Disable short-circuit Boolean expressions.
  411.              Normally, PCQ abandons evaluation of a Boolean
  412.              expression as soon as its overall value becomes
  413.              known (if the left side of an AND expression is
  414.              false, for example, there is no point in
  415.              evaluating the right side).  Thus some parts of
  416.              the program will not be executed.  This option
  417.              forces PCQ to fully evaluate all Boolean
  418.              expressions.
  419.  
  420. The second step takes the assembly language file and creates a new
  421. file that's slightly more efficient.  This is done using the
  422. program Peep, which is invoked with the following command format:
  423.  
  424.         Peep InputAssembly OutputAssembly
  425.  
  426. I normally use the extension ".s" for assembly files that have
  427. been run through the peephole optimizer, but it is entirely up to
  428. you.
  429.  
  430. The third step takes the .asm or .s file and creates an object
  431. file.  An object file is mostly the same machine-readable
  432. instructions and data as the executable file, but it does not
  433. contain all the routines the final program will need.  The
  434. assembler, in this case Charlie Gibbs' A68k, converts assembly
  435. language programs to object files, and is invoked with the
  436. following command line:
  437.  
  438.         A68k InputAssembly OutputObject
  439.  
  440. A68k is a very powerful, flexible program with lots of options -
  441. be sure to read its documentation file for a complete description.
  442.  
  443. If all these steps finished without errors, you can link the
  444. object file to all the routines in the runtime library it needs to
  445. be an executable program.  The Software Distillery linker, Blink,
  446. handles this part of the process.  It is invoked with the
  447. following command line:
  448.  
  449.         Blink InputObject to OutputExec library PCQ.lib
  450.  
  451. Blink also has many options, and comes with a documentation file
  452. that completely explains them.  Note that you might have to use a
  453. full path to specify where PCQ.lib is - if it's in the LIBS:
  454. directory, for example, you would use LIBS:PCQ.lib instead.
  455.  
  456. You now have, finally, a finished executable file.  That seems
  457. like a lot of steps, and a lot to remember, just to make one
  458. program.  It is.  Therefore I use, and have included in the
  459. distribution, a couple of AmigaDOS scripts that automate the whole
  460. process.  The first is called Make, and it compiles a program in
  461. the T:  directory, leaving just the executable program on the
  462. disk.  It looks like this:
  463.  
  464.                 .key source
  465.                 Pascal <source>.p T:<source>.asm
  466.                 A68k T:<source>.asm T:<source>.o
  467.                 Delete T:<source>.asm
  468.                 Blink T:<source>.o to <source> library PCQ.lib
  469.                 Delete T:<source>.o
  470.  
  471. You'll note that my preferences for extensions are built in to
  472. this script - the Pascal file ends in .p, the assembly language
  473. file ends in .asm, and the object file ends in .o.  If you prefer
  474. other names, just change the script.  Also note that you might
  475. have to change the script if your compiler, assembler and linker
  476. are not on the normal path, or if PCQ.lib is not in the current
  477. directory (in both cases, just use the complete path in place of
  478. the file name).  To run this script, you just invoke it like this:
  479.  
  480.         Make ProgramName
  481.  
  482. Note that you leave off any extensions.  If everything works OK,
  483. you'll have an executable program called ProgramName left in the
  484. current directory.  One problem with this script is that you can't
  485. use any command line options on the compiler.  I actually have
  486. several different versions of Make scripts that handle all the
  487. combinations I use.
  488.  
  489. The other script, OMake, is virtually the same, except it also
  490. invokes the peephole optimizer to make slightly more efficient
  491. programs.  It looks like:
  492.  
  493.                 .key source
  494.                 Pascal <source>.p T:<source>.asm
  495.                 Peep T:<source>.asm T:<source>.s
  496.                 Delete T:<source>.asm
  497.                 A68k T:<source>.s T:<source>.o
  498.                 Delete T:<source>.s
  499.                 Blink T:<source>.o to <source> library PCQ.lib
  500.                 Delete T:<source>.o
  501.  
  502. Again, you might have to make modifications to suit your set up.
  503. If you are working on a fairly complex project, you will probably
  504. find it convenient to make a set of specialized scripts to
  505. automate the compile-assemble-link process.
  506.  
  507.  
  508.  
  509.  
  510.  
  511. ===================================================================
  512.  
  513.                         Incompatibilities
  514.  
  515. ===================================================================
  516.  
  517.     PCQ Pascal is incompatible with standard Pascal, and by
  518. extension Turbo Pascal, in several ways.  Briefly, they are:
  519.  
  520.     (1) Sets are not supported.
  521.     (2) The standard Pascal declaration of pointers to records is
  522.         not supported.  For example, the following syntax is legal
  523.         in standard Pascal:
  524.  
  525.             type
  526.                 WindowPtr = ^Window;
  527.                 Window = record
  528.                     NextWindow : WindowPtr;
  529.                     ...
  530.  
  531.         That's an exception in standard Pascal - the only time you
  532.         can use an identifier before you declare it.  In PCQ
  533.         Pascal, that syntax will fail with an Unknown ID error.
  534.         In its place, use something of this form:
  535.  
  536.            type
  537.                Window = record
  538.                    NextWindow : ^Window;
  539.                    ....
  540.                end;
  541.                WindowPtr = ^Window;
  542.  
  543.     (3) Variant records are not supported.
  544.     (4) The familiar syntax for specifying a single quote
  545.         character constant, which in standard Pascal looks like
  546.         '''', is not supported.  Instead PCQ Pascal uses C escape
  547.         conventions, which are explained in the section called
  548.         Strings.
  549.     (5) The way you open a file is different from Standard Pascal,
  550.         although once it's open the commands are basically the
  551.         same.
  552.  
  553.  
  554. Although PCQ Pascal was not designed to be compatible with Turbo
  555. Pascal, in order to make porting programs easier I'll point out a
  556. few of the more important differences (in addition to those
  557. above).
  558.  
  559.     (1) PCQ Pascal handles strings completely differently from
  560.         Turbo Pascal.  PCQ strings are similar to C strings, which
  561.         are not as easy to manipulate as Turbo strings.  In fact,
  562.         PCQ strings are the most difficult of the three.  They are
  563.         fully explained in the Strings section.
  564.     (2) In a PCQ Pascal function, assigning a value to the
  565.         function name causes you to leave the function.  In Turbo
  566.         Pascal, the function name is treated as a write-only
  567.         variable, and you have to use the Exit command explicitly.
  568.         All the examples in the Pascal Report skirt the issue by
  569.         assigning the value as the last statement.
  570.     (3) Speaking of Exit, Exit in PCQ Pascal quits the program,
  571.         whereas in Turbo it quits the current function or
  572.         procedure.  Turbo's "Exit" is like PCQ's "return", and
  573.         Turbo's "Halt" is like PCQ's "Exit".  Got that?
  574.  
  575.  
  576.  
  577.  
  578.  
  579.  
  580. ===================================================================
  581.  
  582.                            PCQ Programs
  583.  
  584. ===================================================================
  585.  
  586. For the most part, PCQ Pascal programs look very much like
  587. standard Pascal programs.  Apart from the incompatibilities
  588. described above, in fact, PCQ should compile plain Pascal programs
  589. directly.  PCQ makes several extensions to Pascal, however, so in
  590. order to explain them I'll go over what is and is not allowed in
  591. PCQ programs.
  592.  
  593.  
  594.  
  595. ===================================================================
  596.  
  597.                           Reserved Words
  598.  
  599. ===================================================================
  600.  
  601. Reserved words are symbols that cannot be used as identifiers in
  602. your program.  They have special meaning to the compiler, and
  603. cannot be overridden.  The reserved words of PCQ are as follows:
  604.  
  605.             and         for         procedure
  606.             array       forward     program
  607.             begin       function    record
  608.             by          goto        repeat
  609.             case        if          return
  610.             const       in          set
  611.             div         label       then
  612.             do          mod         to
  613.             downto      not         type
  614.             else        of          until
  615.             end         or          var
  616.             external    packed      while
  617.             file        private     with
  618.  
  619. As you can see, even the unimplemented stuff is reserved.
  620.  
  621.  
  622.  
  623.  
  624. ===================================================================
  625.  
  626.                      Pascal Program Structure
  627.  
  628. ===================================================================
  629.  
  630. The normal structure of Pascal programs is as follows:
  631.  
  632.  
  633. <Program> ::= Program <Identifier> ; <Block>.  |
  634.               Program <Identifier> (<Identifier List>); <Block>.
  635.  
  636. <Block>   ::= <Declarations> begin <Statements> end |
  637.               begin <Statements> end
  638.  
  639. <Identifier List> ::= <Identifier> , <Identifier List> |
  640.                       <Identifier>
  641.  
  642.  
  643. Does everyone read Backus-Naur?  The idea is that the objects to
  644. the left of the definition sign ::= are being defined by the rule
  645. to the right.  Objects in angle brackets are defined elsewhere in
  646. the list, and the vertical bar character separates alternatives.
  647. Everything else is to be taken literally.  Thus a Pascal program
  648. begins with the literal word Program, followed by an identifier,
  649. followed by a semicolon, followed by a block (whatever that is),
  650. and ending with a period.  On the other hand, it can also consist
  651. of Program followed by an identifier, followed by a left
  652. parenthesis, followed by an identifier list, followed by a right
  653. parenthesis, a semicolon, a block, and finally a period.  Once you
  654. get used to them, BNF diagrams will tell you exactly what you need
  655. to know about the syntax of a program.  BNF grammars can also be
  656. represented as "railroad diagrams", and if this weren't a
  657. text-only document I'd be using them instead.
  658.  
  659. We've left a few things undefined, so we better start filling it
  660. out.
  661.  
  662. <Declarations> ::= <Declaration> , <Declarations> | <Declaration>
  663.  
  664. <Declaration> ::= <Type Declaration>      |
  665.                   <Constant Declaration>  |
  666.                   <Variable Declaration>  |
  667.                   <Label Declaration>     |
  668.                   <Procedure Declaration> |
  669.                   <Function Declaration>
  670.  
  671. Note that standard Pascal imposes an order on the declarations:
  672. it says there should be one constant block, followed by one type
  673. block, etc.  PCQ Pascal removes that restriction, so you can have
  674. as many declarations in whatever order you see fit.
  675.  
  676. Subject to the definition of the rest of those objects, this is
  677. the format for any normal PCQ Pascal program.  There is an
  678. exception (of course):  the separately compilable file.  Turbo
  679. Pascal provides a Unit structure so you can write, compile and
  680. debug units, then use them in many programs.  PCQ provides a
  681. similar, although not as powerful, feature in the form of external
  682. files.  Consider the following extension of our basic rule:
  683.  
  684. <Program> ::= Program <Identifier>; <Block>.  |
  685.               Program <Identifier> (<Identifier List>); <Block>. |
  686.               External ; <Declarations>
  687.  
  688. According to this, an external file is just the reserved word
  689. External followed by a semicolon, then a series of procedures,
  690. functions, whatever.  See the section called External Files for
  691. more information.
  692.  
  693.  
  694.  
  695.  
  696.  
  697. ===================================================================
  698.  
  699.                         Type Declarations
  700.  
  701. ===================================================================
  702.  
  703. Type declarations take the following form:
  704.  
  705. <Type Declaration> ::= Type <Type Definitions>;
  706.  
  707. <Type Definitions> ::= <Type Definition>; <Type Definitions> |
  708.                        <Type Definition>
  709.  
  710. <Type Definition>  ::= <Identifier> = <Type Specification>
  711.  
  712. <Type Specification> ::= <Identifier>                      |
  713.                          <Range>                           |
  714.                          ^<Type Specification>             |
  715.                          (<Identifier List>)               |
  716.                          <Array Definition>                |
  717.                          <Record Definition>               |
  718.                          file of <Type Specification>
  719.  
  720. <Range> ::= <Constant Expression> .. <Constant Expression>
  721.  
  722. <Array Definition> ::= array [<Range>] of <Type Specification> |
  723.                        array <Identifier> of <Type Specification>
  724.  
  725. <Record Definition> ::= record <Variable Definitions> end
  726.  
  727.  
  728. Once you digest the BNF, I think you'll find that straight-
  729. forward.  Constant expressions are discussed in the Expressions
  730. section below - for now let's look at the types that are
  731. predefined in PCQ Pascal.
  732.  
  733.  Numeric Types
  734. ---------------
  735.  
  736. PCQ Pascal supports a variety of numeric types that should give
  737. you the flexibility you need to carry out whatever math you might
  738. require.  The types, from smallest to largest range, are:
  739.  
  740. Byte      This is a 1-byte, unsigned integer, capable of holding
  741.           a value from 0 to 255.
  742.  
  743. Short     A Short is a 2 byte (16 bit) signed integer, with a range
  744.           of -32768 to 32767.
  745.  
  746. Integer   Integer is the largest ordinal type.  It holds a 32-bit
  747.           signed integer, with a range of about -2 billion to 
  748.           2 billion.
  749.  
  750. Real      A floating point value, in Motorola Fast Floating Point
  751.           format.  A Real value is 4 bytes (32 bits), and can
  752.           express floating point values from about 10 x 10^18 to
  753.           about 5 x 10^-20, positive or negative.  I'm not sure
  754.           what the accuracy of FFP is, but I wouldn't count on
  755.           more than 5 or 6 digits.
  756.  
  757. The numeric types are interchangeable in expressions.  If you use
  758. two different types in, for example, a plus expression, the
  759. compiler will automatically promote both values to the smallest
  760. "container type".  A container type is a numeric type whose range
  761. covers both of the arguments.  For example, the result of adding a
  762. Short to an Integer is an Integer.  The result of most binary
  763. operations involving Real values will be a real value.
  764.  
  765.  
  766.  Other Ordinal Types
  767. ---------------------
  768.  
  769. Integers, Shorts and Bytes are all Ordinal types.  This means they
  770. are discrete values that can be represented exactly in binary
  771. (unlike floating point values, which are approximated).  The other
  772. ordinal types are:
  773.  
  774. Char        A one-byte value, stored as the ASCII value.
  775.  
  776. Boolean     Also one byte long, a Boolean value is either -1 (all
  777.             binary ones) for true, or 0 for false.  Anything else
  778.             could produce unpredictable results.  Incidentally,
  779.             the Boolean type can be considered an enumerated type
  780.             with the values True and False.  In most
  781.             implementations False < True and Succ(False) = True,
  782.             but not in PCQ.
  783.  
  784. Enumerated  The values of an enumerated type are specified within
  785.             the program.  If there are 256 or fewer values, the
  786.             enumerated type will be stored in one byte.  If there
  787.             are more, it will be stored in two bytes.  In either
  788.             case, each enumeration is associated with an integer
  789.             value, starting with 0.
  790.  
  791.  
  792.  Pointer Types
  793. ---------------
  794.  
  795. Pointer types hold the address of another variable.  They are all
  796. 32-bit values.  The predefined pointer types are:
  797.  
  798. Address     Address is a special pointer type that is compatible
  799.             with all other pointer types.  It should not be
  800.             dereferenced, but you can use it to avoid cumbersome
  801.             type casts.
  802.  
  803. String      The String type in PCQ is actually defined as a
  804.             pointer to char, although it has other special
  805.             qualities like allowing array-like subscripts.
  806.             Strings are explained in the section called Strings.
  807.  
  808.  
  809.  File Types
  810. ------------
  811.  
  812. Files in PCQ are based on normal AmigaDOS files, but provide
  813. automatic buffering and access to the handy Pascal IO routines
  814. (Writeln, et al).  File variables come in two varieties:
  815.  
  816. Text        A Text file is any normal ASCII file (this
  817.             documentation, for example.
  818.  
  819. Typed Files A typed file, declared as "File of Type", only stores
  820.             values of the given type.  If you issue a Write()
  821.             command on a typed file, PCQ will output the actual
  822.             binary representation of the object to the file.  For
  823.             example, if you have a "File of Integer", the typed
  824.             file will store each Integer as a four-byte binary 
  825.             representation.  A text file, on the other hand, will
  826.             store each Integer as a series of ASCII characters
  827.             from '0' to '9'.  You cannot use Writeln and Readln on
  828.             typed files.
  829.  
  830.  
  831.  
  832.  Type Compatibility
  833. --------------------
  834.  
  835. There are two kinds of type checking.  One is for normal type
  836. compatibility.  That's used for comparing arguments in an
  837. expression, or for formal and actual value parameters.  The second
  838. kind checks for identical types, and is used for more strict
  839. circumstances: in assignment operations and between formal and
  840. actual parameters passed by reference (using the VAR keyword).
  841. PCQ Pascal is, relative to Standard Pascal, generous in its
  842. enforcement of these rules.  For simple type compatibility, the two
  843. types have to pass on of the following tests:
  844.  
  845.       o  They are the same type, or
  846.       o  They are both number types (real, integer, etc), or
  847.       o  They are both arrays with the same size range and the
  848.          element types are compatible, or
  849.       o  They are both pointers to compatible types, or
  850.       o  They are both files of compatible types.
  851.  
  852. Synonym types (e.g. "TYPE ByteSynonym = Byte") are considered
  853. identical types.  For the more strict type identity check, remove
  854. the second rule.
  855.  
  856.  
  857.  
  858.  
  859. ===================================================================
  860.  
  861.                   Constant Declarations
  862.  
  863. ===================================================================
  864.  
  865.  
  866. Constants are normally declared in the Standard Pascal fashion,
  867. which looks like the following in BNF:
  868.  
  869. <Const Block> ::= Const <Const Declarations>;
  870.  
  871. <Const Declarations> ::= <Const Declaration> |
  872.                          <Const Declaration> ; <Const Declarations>
  873.  
  874. <Const Declaration> ::= <Identifier> = <Constant Expression> |
  875.                         <Identifier> : <Type Specification> =
  876.                                         <Typed Constant Value>
  877.  
  878. <Typed Constant Value> ::= <Constant Expression>      |
  879.                            ( <Constant Expressions> ) |
  880.                            @ <Identifier>
  881.  
  882. Constant expressions will be defined below, but you can think of
  883. them as any normal expression that can be completely evaluated
  884. during the compilation (i.e. they use no user-defined functions
  885. and access no variables).
  886.  
  887. Normal constants are easy to understand - they are just like
  888. read-only variables, but they actually take up no memory.  The
  889. constant value is just inserted in the program instead of the
  890. identifier.  Since they are formed by constant expressions, normal
  891. constants can only have a few different types:  integer, real,
  892. char, Boolean, string and array of char.  They can't have any
  893. user-defined type, and can't be record or array types.
  894.  
  895.  
  896.  
  897.  Typed Constants
  898. -----------------
  899.  
  900. That's where typed constants come in.  Typed constants are best
  901. thought of as pre-initialized variables, and they can be of any
  902. type you can define, besides file types.  I have no idea why Turbo
  903. Pascal decided that these objects should be called constants
  904. rather than variables, but I'm following their lead.  Your program
  905. loads with these values already in place, and they will not be
  906. refreshed until the program is reloaded.  They will, therefore,
  907. screw up resident programs if used incorrectly.
  908.  
  909. One handy side effect is that variables local to some procedure
  910. can retain their value throughout a program's execution (like
  911. static variables in C, right?).  In other words, if you declare a
  912. typed constant within a procedure, it will not be accessible to
  913. any code outside of that scope, and it will not lose its value
  914. between calls to the procedure.  Looks like a local, acts like a
  915. global.
  916.  
  917. Declaring typed constants is error prone, and you invariably spend
  918. most of the time counting a list of numbers or trying to match
  919. parentheses or something equally mind-numbing.  Nonetheless, they
  920. are awfully handy.  The syntax corresponds to the second
  921. alternative of the <Const Declaration>, but that doesn't tell the
  922. whole story.  Perhaps it's best to look at some examples:
  923.  
  924.     Type
  925.         ExampleRec = record
  926.                          Field1 : Integer;
  927.                          Field2 : Char;
  928.                          Field3 : Boolean;
  929.                          Field4 : ^Integer;
  930.                          Field5 : Array [-1..1] of Byte;
  931.                      end;
  932.         MultiDim = Array [0..1,0..1] of Integer;
  933.  
  934.     Const
  935.         Message1 : String = "An example string";
  936.         Message2 : Array [0..9] of Char = 'String2   ';
  937.         Message3 : Array [0..9] of Char = ('a','b','c','d','e',
  938.                                            'f','g','h','i','j');
  939.         Value1   : Integer = 456;
  940.         Record1  : ExampleRec =
  941.                         (34, 'r', True, @Value1, (34,56,12));
  942.         Multi1   : MultiDim = ((34,12), (45,15));
  943.  
  944.  
  945. Note that all the "Message" constants and Value1 could also be
  946. specified as normal constants.  Message1 and Value1, in that case,
  947. would not take up any memory, but Messages 2 and 3 would be the
  948. same.  The format of the Message3 declaration is typical for
  949. arrays, but the Message2 format is a special abbreviation for
  950. arrays of char.
  951.  
  952. There are several differences between this and Turbo Pascal's
  953. syntax (all, if I may say so, in favor of PCQ).  First of all,
  954. definitions of constant records in Turbo Pascal requires that you
  955. use the field identifier, followed by a colon, the value, and
  956. possibly a semicolon.  That's far too cumbersome for me, so I just
  957. use the same idea as arrays:  you specify each field, separated by
  958. commas, in order.
  959.  
  960. The second difference with Turbo Pascal is that, until version 6.0,
  961. it only allowed pointer types to be initialized to Nil.  PCQ
  962. Pascal allows you to initialize a pointer type as Nil, or as the
  963. address of a preceding global variable or typed constant.  To do
  964. this, you normally use the '@' operator, which returns the address
  965. of a specified variable.
  966.  
  967. The last difference is that you can use some typed constant values
  968. in subsequent constant expressions.  You can't use any structured
  969. types (i.e. records and arrays), but you can use integers, reals,
  970. and other so-called "simple" types.
  971.  
  972.  Standard Constants
  973. --------------------
  974.  
  975. There are several standard constants (i.e. they are built in to
  976. the compiler itself - you don't have to declare them or use an
  977. include file).  They are:
  978.  
  979.  
  980. False    False is an enumeration of the type Boolean, and has the
  981.          value 0.
  982.  
  983. MaxInt   MaxInt is the largest integer that can be stored in the
  984.          32-bit Integer type.  It is: 2,147,483,647, which is
  985.          $7FFFFFFF in hex.  Thus you can say that the range of an
  986.          Integer variable is +MaxInt to -MaxInt.
  987.  
  988. MaxShort MaxShort is the largest number that can be stored in the
  989.          16-bit Short type.  It turns out to be 32,767, or $7FFF
  990.          in hex.  Just as with MaxInt, you can say that the range
  991.          of a Short variable is +MaxShort to -MaxShort (to be
  992.          precise, the range is actually +MaxShort to
  993.          -(MaxShort+1), and MaxInt is analogous).
  994.  
  995. Nil      Nil is a constant of type Address.  It is defined as
  996.          something like:
  997.  
  998.                 Nil = Address(0);
  999.  
  1000.          In Standard Pascal, "Nil" is a reserved word.  In PCQ
  1001.          Pascal it isn't reserved, for the simple reason that it
  1002.          doesn't have to be.
  1003.  
  1004. True     True is an enumeration of the type Boolean, and actually
  1005.          has the value -1.  In some cases, any non-zero number
  1006.          will suffice, but the "not" operator will behave
  1007.          erratically if you use weird values.
  1008.  
  1009.  
  1010.  
  1011.  
  1012.  
  1013.  
  1014. ===================================================================
  1015.  
  1016.                     Variable Declarations
  1017.  
  1018. ===================================================================
  1019.  
  1020.  
  1021. Variable declarations are handled just like standard Pascal:
  1022.  
  1023. <Var Declaration> ::= Var <Var Definitions> ;
  1024.  
  1025. <Var Definitions> ::= <Var Definition> |
  1026.                       <Var Definition> ; <Var Definitions>
  1027.  
  1028. <Var Definition>  ::= <Identifier List> : <Type Specification>
  1029.  
  1030. Global variables, i.e. variables declared at the outer-most level,
  1031. are allocated as static memory.  All variables declared within a
  1032. procedure or function are allocated on the stack, so if you are
  1033. writing re-entrant routines, be sure to avoid writing to global
  1034. variables.
  1035.  
  1036. Variables larger than one byte are always allocated on word
  1037. boundaries (not longword boundaries - you'll have to use AllocMem
  1038. to guarantee that).  That's an option in Turbo Pascal, but the
  1039. 68000 makes it mandatory for Amiga programs.  Note that this
  1040. applies within records and arrays as well, so be careful if you
  1041. make assumptions about variable size and location.
  1042.  
  1043. Keep in mind that local variables (not typed constants) disappear
  1044. when you leave the function, so you shouldn't try to access them
  1045. afterward (with a pointer variable, for example).  It just won't
  1046. work.
  1047.  
  1048.  
  1049.  Standard Variables
  1050. --------------------
  1051.  
  1052. There are several variables built-in to PCQ Pascal.  They are
  1053. always available, and are treated like global variables.  They
  1054. are:
  1055.  
  1056. CommandLine     This is a String variable that points to the
  1057.                 command line the user entered (with the name of
  1058.                 the program and any indirection parameters
  1059.                 stripped off).  If the program was executed from
  1060.                 the Workbench, this value is not defined.  Note
  1061.                 that, to be on the safe side, this variable should
  1062.                 be treated as read-only.  Make a copy of it if you
  1063.                 want to modify it.
  1064.  
  1065. ExitAddr        ExitAddr is the location within your program that
  1066.                 a runtime error occurred.  If no error occurred,
  1067.                 its value is undefined.  See the section called
  1068.                 "Exit Procedures" for more information.
  1069.  
  1070. ExitCode        This is the Integer value that will be returned to
  1071.                 AmigaDOS when your program terminates.  It is only
  1072.                 defined within an exit procedure.
  1073.  
  1074. ExitProc        This is an Address variable that holds the address
  1075.                 of the first procedure that will be executed when
  1076.                 your program terminates.  See the section called
  1077.                 "Exit Procedures" for more information.
  1078.  
  1079. HeapError       HeapError is an Address variable that holds the
  1080.                 address of a function to call when New() or
  1081.                 AllocString() is unable to allocate a block of
  1082.                 memory.  See the section called Memory Management
  1083.                 for more information.
  1084.  
  1085. Input           Input is a Text file type.  It corresponds to the
  1086.                 standard input channel of the program, such as the
  1087.                 CLI from which it was run.  PCQ Pascal programs
  1088.                 always establish some sort of standard Input file
  1089.                 unless you specifically tell it not to.  See the
  1090.                 section called Input/Output for more information.
  1091.  
  1092. Output          Output is a Text file type.  It corresponds to the
  1093.                 standard output channel of the program, which in
  1094.                 most cases is the CLI from which it was run.  PCQ
  1095.                 Pascal programs always establish an output file
  1096.                 unless instructed not to.
  1097.  
  1098.  
  1099.  
  1100. ===================================================================
  1101.  
  1102.                Procedure and Function Declarations
  1103.  
  1104. ===================================================================
  1105.  
  1106. Procedures and functions allow you to define common routines
  1107. within a larger block.  Procedures are executed by procedure
  1108. statements, and function are executed when they are used in
  1109. expressions.  The format for procedure and function definitions is
  1110. as follows:
  1111.  
  1112.  
  1113. <Proc Declaration> ::= Procedure <Identifier> ; <Body> |
  1114.                        Procedure <Identifier>
  1115.                                 ( <Formal Params> ); <Body>
  1116.  
  1117. <Body> ::= <Block> | External | Forward
  1118.  
  1119. <Formal Params> ::= <Identifier List> : <Type Specification> |
  1120.                     var <Identifier List> : <Type Specification>
  1121.  
  1122. <Func Declaration> ::= Function <Identifier> :
  1123.                                    <Type Specification> ; <Body> |
  1124.                        Function <Identifier> ( <Formal Params> ) :
  1125.                                    <Type Specification> ; <Body>
  1126.  
  1127.  
  1128. At the risk of being repetitive, keep in mind that you can only
  1129. use procedures where the BNF calls for a <Statement>, and you can
  1130. only use functions where the BNF calls for an <Expression>.
  1131.  
  1132.  
  1133.  Parameter Passing
  1134. -------------------
  1135.  
  1136. Pascal provides two different kinds of parameter passing.  The
  1137. first type are called value parameters.  These are the normal
  1138. case.  When you pass a parameter by value, the compiler makes a
  1139. copy of the value, and sends that along.  It's as if someone tells
  1140. you to study the Mona Lisa, providing some photographs for you to
  1141. look at.  You can draw a moustache on the photograph, but it won't
  1142. affect the Mona Lisa, and whatever the procedure or function does
  1143. to the parameter will not affect your original values.  When you
  1144. are calling the procedure, you can use any expression (of the
  1145. correct type, of course) as the actual parameter.
  1146.  
  1147. The other type of parameters are called reference parameters.
  1148. They are specified by preceding the parameter name with the
  1149. reserved word "var" in the procedure or function header.  If you
  1150. use reference parameters, it's as if someone tells you to study
  1151. the Mona Lisa, sends you to the Louvre, and tells you where to
  1152. find the painting.  Thus you are working on the original, and had
  1153. better be careful about it.  Reference parameters must be given as
  1154. variable references - they cannot be full expressions.  Also,
  1155. reference parameters have to pass a stricter type compatibility
  1156. test than value parameters do, since we can't have the procedure
  1157. trying to write a 4-byte Integer into a 1-byte space.
  1158.  
  1159. Normally you should prefer value parameters over reference
  1160. parameters (it tends to cut down on bugs), except in three cases.
  1161. The first is when you actually do want to affect the value of a
  1162. variable.  The second is when the parameter is large.  If you use
  1163. a value parameter, the compiler must make a complete copy of it on
  1164. the stack before it calls the routine, which uses both time and
  1165. stack space.  If you use a reference parameter, the compiler just
  1166. puts the address on the stack.  The third case is when the
  1167. parameter is a file type, in which case it must be passed by
  1168. reference.
  1169.  
  1170. PCQ Pascal pushes arguments on the stack from left-to-right.  C
  1171. compilers, because they have to support variable numbers of
  1172. parameters, push arguments from right-to-left.  Therefore if you
  1173. plan to call C routines, you will have to re-order either the
  1174. order in the call or the order in the routine.
  1175.  
  1176.  
  1177.  Forward Procedures and Functions
  1178. ----------------------------------
  1179.  
  1180. In Pascal, every identifier must be declared before it can be
  1181. used.  This creates problems when procedures or functions are
  1182. mutually dependent, so Pascal allows you to pre-define procedures
  1183. and functions that will be fully defined farther down in the
  1184. source code.
  1185.  
  1186. A forward reference looks just like a normal procedure or function
  1187. declaration, but has the reserved word "Forward" right after the
  1188. header.  The header contains all the information the compiler
  1189. needs to correctly call a routine, so after the forward
  1190. declaration the routine can be used.  When the routine is
  1191. eventually defined, the compiler ensures that it matches up with
  1192. the definition given earlier.  This means that there must be the
  1193. same number of parameters, the parameter types must be the same,
  1194. and if it's a function, the result type must be the same.  Note
  1195. that the actual names of the parameters can be different - only
  1196. their number, order and type are compared.
  1197.  
  1198. A forward reference must be resolved within the same block as it
  1199. was declared, and the same routine cannot be forward-referenced
  1200. more than once.
  1201.  
  1202.  
  1203.  External References
  1204. ---------------------
  1205.  
  1206. External references are very much like forward references - they
  1207. are declarations of routines that aren't actually fully defined.
  1208. The difference is that forward references must be defined later on
  1209. in the same program file, whereas external references are not
  1210. defined in the source file at all.
  1211.  
  1212. The declaration of external references is the same as that of
  1213. forward references, but the reserved word "External" is used in
  1214. place of "Forward".
  1215.  
  1216. External references are used for two main purposes.  First of all,
  1217. they allow you to use procedures and functions defined in External
  1218. files.  All the system routines declared in the include files, for
  1219. example, are actually defined in External files.  They also allow
  1220. you to call routines compiled in a different language, as long as
  1221. you follow some guidelines in parameter passing.  See the section
  1222. called External Files for more information on using external
  1223. routines.
  1224.  
  1225.  
  1226.  Standard Procedures
  1227. ---------------------
  1228.  
  1229. There are several procedures built-in to PCQ Pascal.  They
  1230. include:
  1231.  
  1232.  
  1233.                Close(FileVariable : Any file type)
  1234.  
  1235. The "Close" procedure disassociates the FileVariable from the
  1236. physical disk file, and frees up all the system resources used to
  1237. keep the file open.  See the Input/Output section for more
  1238. information.
  1239.  
  1240.    Dec(V : Any ordinal or pointer) or Dec(V, Amount : Integer)
  1241.  
  1242. Dec (which is short for decrement) subtracts one (or more) from a
  1243. variable.  "Dec(x,n)" is the same as "x := x-n", but slightly more
  1244. efficient.  The variable must be either an ordinal type, like
  1245. Char, Byte, Integer, etc., or a pointer type.  The amount
  1246. parameter, which is optional, must be an integer type - if it is
  1247. not included, the value one is assumed.
  1248.  
  1249. If the variable is an ordinal type, the value is subtracted
  1250. normally.  If the variable is a pointer type, however, Dec()
  1251. multiplies the amount by the size of the type to which the pointer
  1252. refers.  In other words, if you have a pointer p of type ^Integer,
  1253. the statement Dec(p) actually subtracts 4 from the pointer.
  1254.  
  1255.                   Dispose(Variable : ^Anything)
  1256.  
  1257. The "Dispose" procedure frees memory previously allocated with
  1258. "New" (see below).  See the section called Memory Management for
  1259. information on PCQ's memory routines.
  1260.  
  1261.                 Exit or Exit(ReturnCode : Integer)
  1262.  
  1263. Exit, like the AmigaDOS and the C function of the same name,
  1264. terminates the program.  If a return code is specified, it is
  1265. returned to AmigaDOS.  By convention, return codes are normally 5
  1266. for small problems (warnings), 10 for significant problems
  1267. (errors), and 20 when everything goes wrong (failure).  Using Exit
  1268. without a return code is the same as Exit(0), which indicates that
  1269. everything is O.K.
  1270.  
  1271. Exit is the system-safe way to quit a program - you should not
  1272. call AmigaDOS's DOSExit() routine.  When you call Exit, all the
  1273. exit procedures are called in turn.  This includes the standard
  1274. routine that closes all open files and deallocates memory, as well
  1275. as any that you define.
  1276.  
  1277.                Get(var FileVariable : A file type)
  1278.  
  1279. The "Get" procedure moves the file pointer to the next element in
  1280. the file, without actually reading any element in.  The element in
  1281. the file buffer can be accessed through the FileVariable^ syntax.
  1282. See the Input/Output section for details.
  1283.  
  1284.           Inc(VarReference: Ordinal or Pointer type) or
  1285.      Inc(VarReference : Ordinal or Pointer, Amount : Integer)
  1286.  
  1287. The "Inc" command adds an integer Amount to the variable
  1288. VarReference.  If no amount is specified, it is assumed to be 1.
  1289. If the variable is an ordinal type the addition is carried out
  1290. normally, but if it is a pointer type the amount is first
  1291. multiplied by the size of the object to which the pointer refers.
  1292. In other words, Inc(p), where p is a pointer to Integer, actually
  1293. adds 4 (the size of an Integer in bytes) to p.
  1294.  
  1295.                    New(PointerVar : ^Anything)
  1296.  
  1297. The "New" procedure allocates a block of memory equal in size to
  1298. the type to which the variable (which must be a pointer type)
  1299. points.  The address of the newly allocated block will be assigned
  1300. to the variable.  See the section called Memory Management for
  1301. more information.
  1302.  
  1303.                Put(var FileVariable : A file type)
  1304.  
  1305. The "Put" routine advances the file pointer past the current
  1306. element, writing the current element to disk if necessary.  The
  1307. current element can be set through the FileVariable^ syntax.  See
  1308. the section called Input/Output for details.
  1309.  
  1310.  Read(var FileVariable :  Text or File, Variable References....)
  1311.  
  1312. The "Read" procedure inputs information from an AmigaDOS file.
  1313. The FileVariable is optional, and the procedure is one of the very
  1314. few in Pascal that can take a variable number of arguments.  See
  1315. the Input/Output section for more information.
  1316.  
  1317.      Readln(var FileVariable : Text, Variable References....)
  1318.  
  1319. The "Readln" procedure is very similar to "Read", but it can only
  1320. be used on Text files, and after it has read all the arguments it
  1321. requires, it continues to eat characters until it is at the
  1322. beginning of the next line.  See the Input/Output section for more
  1323. information.
  1324.  
  1325.                Reset(var FileVar : File or Text;
  1326.                         FileName : String;
  1327.                       BufferSize : Integer);
  1328.  
  1329. The "Reset" procedure opens a file for reading.  The BufferSize
  1330. parameter is optional.  If you have used the {$I-} directive to
  1331. indicate manual IO checking, you should be sure to check IOResult
  1332. to see if the file opened correctly.  If you are using automatic
  1333. IO checking, the program will terminate with a runtime error if
  1334. the file does not open correctly.  See the Input/Output section
  1335. for more information.
  1336.  
  1337.              Rewrite(var FileVar : File or Text;
  1338.                         FileName : String;
  1339.                       BufferSize : Integer);
  1340.  
  1341. The "Rewrite" procedure opens a file for output, erasing any
  1342. existing file of the same name.  The BufferSize argument is
  1343. optional.  If the file cannot be opened, IOResult will be set to a
  1344. non-zero value.  If you are using automatic IO checking, that will
  1345. cause your program to terminate with a runtime error.  If you are
  1346. using manual IO checking, be sure to look at IOResult to be sure
  1347. the file is open.  See the Input/Output section for more
  1348. information.
  1349.  
  1350.                      Trap(TrapNum : Integer)
  1351.  
  1352. The "Trap" procedure can be used by some debuggers as a sort of
  1353. automatic breakpoint.  If you insert the correct trap, your
  1354. debugger might stop at that location.  Then again it might not.
  1355.  
  1356.        Write(FileVariable : Text or File, Expressions....)
  1357.  
  1358. The "Write" procedure outputs information to an AmigaDOS file.
  1359. The FileVariable is optional, and it can take a variable number of
  1360. arguments.  See the Input/Output section for details.
  1361.  
  1362.           Writeln(FileVariable : Text, Expressions....)
  1363.  
  1364. The "Writeln" procedure is very similar to "Write", but it only
  1365. works on Text files, and it terminates the line after writing all
  1366. of its arguments.  Again, see the Input/Output section for more
  1367. information.
  1368.  
  1369.  
  1370.  Standard Functions
  1371. --------------------
  1372.  
  1373. There are also a bunch of functions built in to the Pascal
  1374. compiler.  They are:
  1375.  
  1376.  
  1377.                 Adr(Variable Reference) : Address
  1378.  
  1379. The Adr() function returns the actual address in memory of the
  1380. parameter.  This is equivalent to Turbo Pascal's Addr() function,
  1381. and as in Turbo Pascal you can also use the @ operator.
  1382.  
  1383.            Abs(numeric expression) : same numeric type
  1384.  
  1385. The function call Abs(n) returns n, if n is positive, and -n if n
  1386. is negative.
  1387.  
  1388.             ArcTan(numeric Expression) : Real radians
  1389.  
  1390. The ArcTan() function returns the approximate arctangent of the
  1391. parameter in radians.
  1392.  
  1393.                   Bit(BitNumber) : Mask Integer
  1394.  
  1395. The Bit() function returns an Integer with just the specified bit
  1396. set.  It is equivalent to (1 shl BitNumber).
  1397.  
  1398.                   Chr(numeric expression) : Char
  1399.  
  1400. The Chr() function transforms any numeric type into its ASCII
  1401. character equivalent.
  1402.  
  1403.                    Ceil(Real expression) : Real
  1404.  
  1405. Ceil() returns the least integer greater than or equal to the
  1406. parameter.
  1407.  
  1408.             Cos(numeric expression in radians) : Real
  1409.  
  1410. The Cos() function returns the cosine of the given angle measured
  1411. in radians.
  1412.  
  1413.                EOF(file or Text variable) : Boolean
  1414.  
  1415. EOF returns True if the file is at the end-of-file position, or
  1416. False otherwise.  The EOF function is only valid for files opened
  1417. for input.  See the section called Input/Output for more
  1418. information.
  1419.  
  1420.                    Exp(numeric expression) : Real
  1421.  
  1422. The function Exp(x) returns e raised to the xth power.  In case
  1423. it slipped your mind, e is about 2.71828....
  1424.  
  1425.                  Float(Integer expression) : Real
  1426.  
  1427. The Float() function converts any Integer type expression to its
  1428. floating point representation.  If the integer is fairly large, it
  1429. might be approximated.  Thus "Trunc(Float(IntVar)) = IntVar" is
  1430. not always true.
  1431.  
  1432.                   Floor(Real expression) : Real
  1433.  
  1434. The Floor() function returns the largest whole number less than or
  1435. equal to the parameter.
  1436.  
  1437.                         IOResult : Integer
  1438.  
  1439. The IOResult() function checks to see if any errors have occurred
  1440. since the last time you checked.  Normally, PCQ Pascal inserts
  1441. statements to check the IOResult automatically, but if you have
  1442. set IO checking off (using the {$I-} directive), you'll have to
  1443. check it explicitly.  The act of checking it erases it, so if you
  1444. need to re-use it you'll have to save it in a variable.  See the
  1445. Input/Output section for more information.
  1446.  
  1447.                   Ln(numeric expression) : Real
  1448.  
  1449. The Ln() function returns the natural logarithm (i.e. the
  1450. logarithm to the base e) of the parameter.
  1451.  
  1452.                  Odd(numeric expression) : Boolean
  1453.  
  1454. The Odd() function returns TRUE if its argument is odd, and FALSE
  1455. otherwise.
  1456.  
  1457.                Open(fname      : String;
  1458.                     var fvar   : file or Text;
  1459.                     BufferSize : Integer) : Boolean;
  1460.  
  1461. Open is the function form of the Rewrite procedure.  It opens a
  1462. file for output, erasing any existing file with the same name.  If
  1463. the file opens correctly, Open returns True.  If not, it returns
  1464. False.  The BufferSize parameter is optional.  See the section
  1465. called Input/Output for more information.
  1466.  
  1467.                 Ord(Ordinal expression) : Integer
  1468.  
  1469. The Ord() function returns the ordinal value of the argument as an
  1470. Integer.  In other words, it can convert Chars, Booleans, and
  1471. enumerated types into their numeric equivalents.  Since it
  1472. actually changes the type of the argument into an Integer it is
  1473. referred to as a transfer function.
  1474.  
  1475.                Pred(Ordinal expression) : same type
  1476.  
  1477. The Pred() function returns the next least ordinal value in the
  1478. same type.  For example, Pred(2) is 1.  If the argument is the
  1479. lowest value within the type (such as Pred(ByteVar) where ByteVar
  1480. is zero), its behavior is undefined.
  1481.  
  1482.              ReOpen(fname      : String;
  1483.                     var fvar   : file or text;
  1484.                     buffersize : Integer) : Boolean
  1485.  
  1486. ReOpen is the function form of Reset.  It opens a file for
  1487. reading, and returns True if everything went O.K.  If for any
  1488. reason the file did not open correctly, ReOpen returns False.  The
  1489. BufferSize parameter is optional, and can be any amount.  See the
  1490. section called Input/Output for more information.
  1491.  
  1492.                  Round(Real expression) : Integer
  1493.  
  1494. The Round() function rounds a real expression to the nearest
  1495. Integer.  It is actually implemented as Trunc(value + 0.5), so it
  1496. takes somewhat longer to execute than the Trunc function.  Also,
  1497. it always rounds 0.5 up.
  1498.  
  1499.             Sin(numeric expression in radians) : Real
  1500.  
  1501. The Sin() function computes the sine for the given angle measured
  1502. in radians.
  1503.  
  1504.                 SizeOf(Type Identifier) : Integer
  1505.  
  1506. The SizeOf() function returns the actual size of the given type.
  1507. Note that the type must be specified as a single identifier.
  1508.  
  1509.                Sqr(numeric expression) : same type
  1510.  
  1511. The function Sqr(x) returns x*x.
  1512.  
  1513.                  Sqrt(numeric expression) : Real
  1514.  
  1515. The function Sqrt(x) returns the square root of x.  In other
  1516. words, Sqrt(x) * Sqrt(x) = x.
  1517.  
  1518.                Succ(Ordinal expression) : same type
  1519.  
  1520. The Succ() function returns the next greater ordinal value within
  1521. the same type.  If that value is not defined (for example, Succ(n)
  1522. where n is the largest enumeration within a type), the function is
  1523. not defined.
  1524.  
  1525.             Tan(numeric expression in radians) : Real
  1526.  
  1527. Returns the tangent of the angle measured in radians.  If the
  1528. parameter is an odd multiple of Pi/2, this function will take on
  1529. meaningless values (the tangent function is undefined at odd
  1530. multiples of Pi/2).
  1531.  
  1532.                  Trunc(real expression) : Integer
  1533.  
  1534. The Trunc() function returns the integer portion of a floating
  1535. point number.  It is the fastest way to convert a real value to an
  1536. Integer value.
  1537.  
  1538.  
  1539.  
  1540.  
  1541.  
  1542. ===================================================================
  1543.  
  1544.                         Label Declarations
  1545.  
  1546. ===================================================================
  1547.  
  1548. Labels must be declared in the declaration section before they can
  1549. be used in the program.  The label declaration section has the
  1550. following form:
  1551.  
  1552. <Label Declarations> ::= Label <Identifiers> ;
  1553.  
  1554. <Identifiers> ::= <Identifier> | <Identifier> , <Identifiers>
  1555.  
  1556. Note that Standard and Turbo Pascal also allow labels to have
  1557. numeric values, but PCQ Pascal only allows normal identifiers to
  1558. be used.  If you run across a program with numeric labels, you can
  1559. just put some letter on the front to make them legal identifiers.
  1560. Perhaps a better solution would be to trash the program.
  1561.  
  1562.  
  1563.  
  1564.  
  1565.  
  1566. ===================================================================
  1567.  
  1568.                            Expressions
  1569.  
  1570. ===================================================================
  1571.  
  1572. PCQ Pascal accepts expressions very similar in form to just about
  1573. all Pascal implementations.  It's probably very familiar to you,
  1574. but just to be on the safe side, we'll define it.  Let's start off
  1575. with the constants accepted by PCQ:
  1576.  
  1577.  
  1578. <digit>         ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
  1579.  
  1580. <digits>        ::= <digit> | <digit> <digits>
  1581.  
  1582. <binary digit>  ::= 0 | 1
  1583.  
  1584. <binary digits> ::= <binary digit> | 
  1585.                     <binary digit> <binary digits>
  1586.  
  1587. <hex digit>     ::= <digit> | a | b | c | d | e | f
  1588.  
  1589. <hex digits>    ::= <hex digit> | <hex digit> <hex digits>
  1590.  
  1591. <Float Const>   ::= <digits> . <digits>
  1592.  
  1593. <Integer Const> ::= <digits> | $ <hex digits> | % <binary digits>
  1594.  
  1595. <Char Value>    ::= <ASCII char> | \ <escape sequence>
  1596.  
  1597. <Char Values>   ::= <Char Value> | <Char Value> <Char Values>
  1598.  
  1599. <Number Const>  ::= <Integer Const> | <Float Const>
  1600.  
  1601. <Char Const>    ::= ' <Char Value> '
  1602.  
  1603. <String Const>  ::= " <Char Values> "
  1604.  
  1605. <Char Array Const> ::= ' <Char Values> '
  1606.  
  1607.  
  1608. That should confuse things a bit.  What it says is that whenever
  1609. the compiler expects an integer, you can use decimal, hexadecimal
  1610. or binary representation.  It also says that floating point
  1611. constants are only recognized in the normal 23.23 form, without
  1612. any trailing exponent.  Finally, it says that you can use C-style
  1613. escape sequences for any text constant - these escape values are
  1614. discussed in the Strings section.
  1615.  
  1616. So how are these things grouped into complete expressions?
  1617. Consider the following definitions:
  1618.  
  1619. <expression> ::= <simple> <rel op> <simple> | <simple>
  1620.  
  1621. <rel op>     ::= = | <> | < | > | <= | >=
  1622.  
  1623. <simple>     ::= <term> <add op> <term> | <term>
  1624.  
  1625. <add op>     ::= + | - | or | xor
  1626.  
  1627. <term>       ::= <factor> <mul op> <factor> | <factor>
  1628.  
  1629. <mul op>     ::= * | / | div | mod | and | shr | shl
  1630.  
  1631. <factor>     ::= <Number Const>         |
  1632.                  <Sign> <Number Const>  |
  1633.                  <Char Const>           |
  1634.                  <String Const>         |
  1635.                  <Char Array Const>     |
  1636.                  <Variable Reference>   |
  1637.                  @ <Variable Reference> |
  1638.                  not <factor>           |
  1639.                  ( <Expression> )       |
  1640.                  <Function call>
  1641.  
  1642.  
  1643. What does all this mean?  It means that expressions are built up
  1644. from factors, the basic blocks of an expression.  A factor can be
  1645. a constant, a variable, a parenthesized expression, and all the
  1646. other things listed.  The following examples are all factors:
  1647.  
  1648.                                 23
  1649.                            (4.0 - 2.3)
  1650.                             %01000001
  1651.                                'a'
  1652.                      RecordPtr^.Field1[45,23]
  1653.                               @Var1
  1654.                             Abs(Var2)
  1655.  
  1656. Factors can have a unary operator (an operator that applies to
  1657. only one value, unlike binary operators that apply to two).  They
  1658. are:
  1659.  
  1660.         @   This operator is the address-of operator.  The returns
  1661.             the address of the variable reference immediately
  1662.             following.  It is equivalent to the Adr() function.
  1663.         -   Sign negation.  Takes the negation of the factor
  1664.             following it.
  1665.         +   Sign identity.  It is accepted, but has no affect.
  1666.        not  Boolean or bitwise negation.  If the factor is a
  1667.             Boolean value, this returns the opposite.  If it is an
  1668.             integer type, it returns the bitwise compliment.
  1669.  
  1670. These factors are built into terms.  Terms are either the same as
  1671. factors, or two factors with a multiplicative operator between
  1672. them.  The multiplicative operations are the following:
  1673.  
  1674.         *   Multiplication
  1675.         /   Floating point division.  Both arguments to this
  1676.             operator are converted to floating point before the
  1677.             operation takes place.
  1678.        div  Integer division.  Both arguments to this operator
  1679.             are converted to integer forms before the operation
  1680.             takes place.
  1681.        mod  The remainder operation.  Both arguments are
  1682.             converted to integers if necessary.
  1683.        and  Logical AND function.  If both arguments are Boolean
  1684.             values and the left factor evaluates to FALSE, this
  1685.             operation will "short-circuit".  Any Real factors are
  1686.             converted to Integers.
  1687.        shl  Shift left.  Shifts the bits in the left operand the
  1688.             number of positions given by the right operand.  Both
  1689.             arguments are converted to Integers if necessary.
  1690.        shr  Shift right.  Shifts the bits in the right operand
  1691.             the number of positions given by the right operand.
  1692.             This is a logical shift, not arithmetic, so the
  1693.             left-most bit is assigned 0.  Thus if you shift a
  1694.             negative number in order to do division, you will get
  1695.             nonsense results (use div instead - it will use shifts
  1696.             when possible).  Both arguments are converted to
  1697.             Integers.
  1698.  
  1699. Terms, in turn, are built into simple expressions.  Simple
  1700. expressions are either the same thing as terms, or two terms
  1701. grouped by an addition operator.  The addition operators are:
  1702.  
  1703.         +   Adds the two operands.
  1704.         -   Subtracts the second operand from the first.
  1705.         or  Logical OR.  If both operands are Boolean values and
  1706.             the left operand evaluates to TRUE, the right operand
  1707.             is not evaluated.  Both arguments are converted to
  1708.             Integers if necessary.
  1709.        xor  Exclusive OR.  Generates the left term exclusive ORed
  1710.             with the right term.  This never short circuits.  If
  1711.             either argument is a Real value, it is converted to an
  1712.             Integer.
  1713.  
  1714. These simple expressions are built into complete expressions.
  1715. Expressions are either the same thing as simple expressions, or
  1716. two simple expressions grouped by a relative operator.  These
  1717. operators produce Boolean results, and are defined as:
  1718.  
  1719.         =   Returns TRUE iff the two arguments are equal.
  1720.         <>  Returns TRUE iff the two arguments are not equal.
  1721.         >   Returns TRUE iff the left argument is greater than the
  1722.             right argument.
  1723.         <   Returns TRUE iff the left argument is less than the
  1724.             right argument.
  1725.         >=  Returns TRUE iff the left argument is either greater than
  1726.             or equal to the right argument (that's only takes one
  1727.             comparison, by the way).
  1728.         <=  Returns TRUE iff the left argument is either less than
  1729.             or equal to the right argument.
  1730.  
  1731.         (iff is shorthand for "if and only if")
  1732.  
  1733.  
  1734.  Evaluation Order & Short Circuits
  1735. --------------------------------------------------
  1736.  
  1737. The normal rules of math are built-in to the grammar for
  1738. expressions.  The unary operators are evaluated first, then all
  1739. the multiplicative operations, the additive operations, and
  1740. finally the relative operations.  Thus the precedence looks like
  1741. this:
  1742.  
  1743.         Operator              Precedence
  1744.       -------------------------------------
  1745.         @,not,unary +/-     First (highest)
  1746.  
  1747.         *,/,div,mod,
  1748.         and,shr,shl         Second
  1749.  
  1750.         +,-,or,xor          Third
  1751.  
  1752.         =,<>,<,>,>=,<=      Fourth (lowest)
  1753.  
  1754. All expressions in parentheses are, of course, evaluated first.
  1755. Also, keep in mind that all of these operators are left
  1756. associative - in other words, a factor between two operators of
  1757. equal precedence is bound to the one on the left (e.g.  "x+y+z" is
  1758. treated as "(x+y)+z").
  1759.  
  1760. You should not make any conclusions about the order in which the
  1761. two operands to a binary operator are evaluated.  If you have the
  1762. expression "function1 + function2" in your program, for example,
  1763. there is no telling which function would be evaluated first.
  1764.  
  1765. The exception to that rule is for Boolean equations, but only if
  1766. you are using short-circuit evaluations (the default).  What is a
  1767. short circuit?  Imagine you have the expression "A or B" in your
  1768. program.  If the program evaluates A and finds that it is True, it
  1769. already knows the final value of the entire expression.  Therefore
  1770. there's no point in evaluating B.  The analogous case for "A and
  1771. B" occurs when A evaluates to False.  You can be sure, in a
  1772. Boolean expression, that the operands of "and" and "or" will be
  1773. evaluated left-to-right.
  1774.  
  1775. Short-circuit evaluations are often faster than normal ones, but
  1776. they have the added benefit of protecting the programmer.  For
  1777. example, the statement:
  1778.  
  1779.         if OpenMyWindow(w) and (w^.Width = whatever) then ....
  1780.  
  1781. ... would be a problem without short-circuit evaluations because,
  1782. for example, the variable w might not be defined if the function
  1783. call fails.  The value of the function would not change, but if
  1784. w pointed to an odd address it could cause a guru.  With
  1785. short-circuit evaluations, the second factor would not be
  1786. evaluated unless the first returned True.
  1787.  
  1788.  
  1789.  Constant Expressions
  1790. ----------------------
  1791.  
  1792. Constant expressions are the same as normal expressions, but must
  1793. be completely evaluated at compile time.  Thus they can't use any
  1794. external functions or variable references, but can use all the
  1795. same operators and the standard functions (i.e. the ones built-in
  1796. to the compiler).
  1797.  
  1798.  
  1799.  Variable References
  1800. ---------------------
  1801.  
  1802. Variable references can get awfully complex, what with pointers
  1803. and records and arrays and so forth.  The basic syntax is as
  1804. follows:
  1805.  
  1806. <Variable Reference> ::= <Variable Mark> |
  1807.                          <Variable Mark> <Selectors>
  1808.  
  1809. <Variable Mark> ::= <Variable ID> |
  1810.                     <Type ID> ( <Variable Reference> )
  1811.  
  1812. <Selectors>  ::= <Selector> | <Selector> <Selectors>
  1813.  
  1814. <Selector>   ::= ^ | .<Field Id> | [ <Index Expressions> ]
  1815.  
  1816.  
  1817. Generally speaking, a variable reference will consist of the
  1818. identifier of a global or local variable, followed by any number
  1819. of selectors in any combination.  The other possibility, which is
  1820. somewhat different as of version 1.2 of the compiler, is that you
  1821. can place a type cast somewhere in the middle of all this.  The
  1822. following are all examples of variable references:
  1823.  
  1824.         Var1
  1825.         Var1^
  1826.         Var1^.Field1[34,56]
  1827.         Type2(Var1)^.Field2^^[23]
  1828.  
  1829. If you start writing code that looks like the last example, you
  1830. should get some rest.
  1831.  
  1832.  
  1833.  
  1834.  
  1835. ===================================================================
  1836.  
  1837.                           Statements
  1838.  
  1839. ===================================================================
  1840.  
  1841. Statements are the meat and potatoes of programs - they are what
  1842. goes between begin and end.  They have the following form:
  1843.  
  1844. <Statement>   ::= <If Statement>         |
  1845.                   <While Statement>      |
  1846.                   <Repeat Statement>     |
  1847.                   <For Statement>        |
  1848.                   <Case Statement>       |
  1849.                   <With Statement>       |
  1850.                   <Compound Statement>   |
  1851.                   <Assignment Statement> |
  1852.                   <Procedure Call>       |
  1853.                   <Return Statement>     |
  1854.                   <Goto Statement>
  1855.  
  1856.  
  1857.  If Statements
  1858. ---------------
  1859.  
  1860. The if statement allows you to test alternatives.  It has the
  1861. following form:
  1862.  
  1863. <If Statement> ::= if <Boolean Expr> then <Statement> |
  1864.                    if <Boolean Expr> then <Statement>
  1865.                                      else <Statement>
  1866.  
  1867. If the Boolean expression evaluates to True, the statement
  1868. following the word "then" is executed.  If the Boolean expression
  1869. evaluates to False, the statement in the else clause, if one
  1870. exists, is evaluated.  If no else clause exists, execution
  1871. continues with the statement following the "if" statement.
  1872.  
  1873. There is an ambiguity here - consider the following fragment:
  1874.  
  1875.         if Expr then if Expr then Statement1 else Statement2
  1876.  
  1877. To which "if" test does the else clause apply?  PCQ, like most
  1878. implementations, always attaches the else part to the most recent
  1879. "if".
  1880.  
  1881.  
  1882.  While Statements
  1883. ------------------
  1884.  
  1885. The "while" statement is one of several that allow you to loop.
  1886. It has the following form:
  1887.  
  1888. <While Statement> ::= while <Boolean Expr> do <Statement>
  1889.  
  1890. At the beginning of the loop, the Boolean expression is evaluated.
  1891. If it evaluates to True, the statement part is executed.  When
  1892. that finishes, the expression is re-evaluated, and the process
  1893. continues until the expression evaluates to False.  Once that
  1894. happens, execution continues with the statement following the
  1895. while statement.
  1896.  
  1897.  
  1898.  Repeat Statements
  1899. -------------------
  1900.  
  1901. The "repeat" statement provides a slightly different form of
  1902. looping.  It has the following form:
  1903.  
  1904. <Repeat Statement> ::= repeat <Statements> until <Boolean Expr>
  1905.  
  1906. <Statements> ::= <Statement> | <Statement> ; <Statements>
  1907.  
  1908. When the repeat statement is encountered, the statement part is
  1909. executed, then the Boolean expression is evaluated.  If the
  1910. expression evaluates to False, the statement part is executed
  1911. again.  If the expression evaluates to True, execution continues
  1912. at the following statement.  Note that "repeat" loops always
  1913. execute at least once, whereas "while" loops might not execute at
  1914. all.  Also note that the <Statements> part can actually be empty.
  1915.  
  1916.  
  1917.  For Statements
  1918. ----------------
  1919.  
  1920. The "for" statement provides a third type of looping, for
  1921. occasions when you know exactly how many iterations of the loop
  1922. you want to execute.  It has the following form:
  1923.  
  1924. <For Statement> ::= for <Variable Reference> :=
  1925.                         <Expression> <Direction>
  1926.                         <Expression> do <Statement>
  1927. <Direction> ::= to | downto
  1928.  
  1929. Note that this is different from the PCQ version 1.1.  When a
  1930. "for" loop is encountered, the first expression (the initial
  1931. value) is evaluated, and its value is stored in the variable
  1932. reference (called the index).  Then the index is compared to the
  1933. second expression (the final value).  If the direction is "to",
  1934. and the index is less than or equal to the final value, the
  1935. statement part is executed.  At the end of that, the index is
  1936. incremented by one and again tested against the final value.  This
  1937. goes on until the index is greater than the final value, at which
  1938. time execution moves on to the next statement.
  1939.  
  1940. If the direction is "downto", the same thing happens, except the
  1941. index is decremented at each pass, and looping continues until the
  1942. index is less than the final value.
  1943.  
  1944. Note that the "for" loop might not execute at all, if the initial
  1945. value is larger than the final value (for "to" loops, or vice
  1946. versa for "downto" loops).  Also note that the final value is
  1947. fully evaluated each time through the loop, so if it's a complex
  1948. expression you might want to store it in a variable before the
  1949. "for" statement.
  1950.  
  1951. You can always use a "while" or "repeat" loop in place of a "for"
  1952. loop, and in fact the "for" loop is least often used.  Niklaus
  1953. Wirth, the guy who designed Pascal and Modula-2, actually left the
  1954. statement out of his latest language (Oberon).
  1955.  
  1956. It is considered an error to modify the index variable within the
  1957. loop, but PCQ Pascal doesn't enforce it.  That doesn't make it a
  1958. good idea, of course.
  1959.  
  1960.  
  1961.  Case Statements
  1962. -----------------
  1963.  
  1964. The Case statement is used to test a value against a series of
  1965. alternatives, and process instructions accordingly.  It has the
  1966. following form:
  1967.  
  1968. <Case Statement> ::= case <Expression> of <Alternatives> end |
  1969.                      case <Expression> of <Alternatives>
  1970.                                        else <Statement> end
  1971.  
  1972. <Alternatives> ::= <Alternative> | <Alternative> ; <Alternatives>
  1973.  
  1974. <Alternative> ::= <Case Vals> : <Statement>
  1975.  
  1976. <Case Vals> ::= <Case Val> | <Case Val> , <Case Vals>
  1977.  
  1978. <Case Val>  ::= <Const Expr> | <Const Expr> .. <Const Expr>
  1979.  
  1980. When the case statement is executed, the expression is evaluated.
  1981. It is then compared against all of the cases and ranges until it
  1982. matches one, at which point the associated statement is executed.
  1983. If none of the alternatives match, the else statement is executed,
  1984. if there is one.  If not, execution just continues with the
  1985. statement following the case statement.
  1986.  
  1987. Note that the expression is only evaluated once, so a case
  1988. statement can be more efficient than an equivalent series of "if"
  1989. statements.  Also note that one statement (at most) from the case
  1990. statement is executed - it's not like C, where execution falls
  1991. through until you tell it to knock it off.
  1992.  
  1993.  
  1994.  With Statements
  1995. -----------------
  1996.  
  1997. The With statement allows to specify a record variable to which a
  1998. statement will apply.  Within the statement you can abbreviate
  1999. references to the record's fields by specifying just the field
  2000. name.  That saves you some typing, and the compiler generates
  2001. somewhat more efficient code.  It serves no functional purpose.
  2002. The format of a With statement is as follows:
  2003.  
  2004. <With Statement> ::= with <Expressions> do <Statement>
  2005.  
  2006. <Expressions> ::= <Expression> | <Expression> , <Expressions>
  2007.  
  2008. If you specify more than one record (separated by commas), the
  2009. compiler treats it like nested with statements, with the first
  2010. record listed at the outermost scope and the last one at the
  2011. innermost.
  2012.  
  2013. In the statement, any references to fields will be considered to
  2014. apply to the innermost record to which it applies.  Ambiguities
  2015. can be cleared up by using the full record specification.
  2016.  
  2017. With statements are especially handy when the record reference is
  2018. long and convoluted - it will only be executed once, which
  2019. increases efficiency.  The other time it comes in especially handy
  2020. is filling in values in a record.  It doesn't always improve the
  2021. program's efficiency, but it saves a lot of typing.
  2022.  
  2023. If you are executing under a with statement of the form "with p^
  2024. do ...", it is considered an error to alter the value of p.  For
  2025. example, it is an error to free the memory of a record in a "with"
  2026. statement referencing the record.  This error is not detected by
  2027. PCQ Pascal, but it's a good idea to avoid it.
  2028.  
  2029.  
  2030.  Compound Statements
  2031. ---------------------
  2032.  
  2033. The compound statement allow you to use a series of statements in
  2034. any situation that calls for at least one statement.  It has the
  2035. following form:
  2036.  
  2037. <Compound Statement> ::= begin <Statements> end
  2038.  
  2039. A compound statement can in fact be used wherever a statement is
  2040. allowed, and the compound statement by itself generates no extra
  2041. code.  In other words, surrounding a group of expressions with
  2042. "begin" and "end" will not change the code the compiler produces -
  2043. it just clarifies your purpose.
  2044.  
  2045.  
  2046.  Assignment Statements
  2047. -----------------------
  2048.  
  2049. Assignment statements are used to set the value of variables.
  2050. They have the following form:
  2051.  
  2052. <Assignment Statement> ::= <Variable Reference> := <Expression>
  2053.  
  2054. Remember that the type of the variable must match the type of the
  2055. expression identically (see the section called Type Declarations
  2056. for the specific rules).
  2057.  
  2058.  
  2059.  Procedure Calls
  2060. -----------------
  2061.  
  2062. Procedure calls transfer execution to a pre-defined routine,
  2063. passing parameters as required.  They have the following form:
  2064.  
  2065. <Procedure Call> ::= <Identifier> |
  2066.                      <Identifier> ( <Actual Params> )
  2067.  
  2068. <Actual Params> ::= <Actual Param> |
  2069.                     <Actual Param> ; <Actual Params>
  2070.  
  2071. <Actual Param> ::= <Expression>
  2072.  
  2073. Procedures are different from functions in that functions return a
  2074. value, and are callable only from expressions.  Procedures do not
  2075. return a value, and are callable only from statements.
  2076.  
  2077. When a procedure statement is executed, each actual parameter is
  2078. evaluated and pushed on the stack, in left to right order.
  2079. Because C uses variable numbers of parameters, it pushes actual
  2080. parameters on the stack in right to left order.  Therefore if you
  2081. plan to call a C routine you will need to reverse the order of the
  2082. parameters.
  2083.  
  2084.  
  2085.  Return Statements
  2086. -------------------
  2087.  
  2088. Normally, execution of a procedure continues until the end of the
  2089. procedure, when execution returns to the caller.  The "return"
  2090. statement allows you to escape the current procedure immediately.
  2091. It has the following very simple form:
  2092.  
  2093.     <Return Statement> ::= return
  2094.  
  2095. The "return" statement is only valid within procedures.  It is not
  2096. valid within functions because they must return a value - the
  2097. analogous statement in a function is an assignment to the function
  2098. identifier, which causes the function to return immediately.  The
  2099. "return" statement is also not valid in the main body of the
  2100. program, because it would cause the program to terminate.  Instead
  2101. you must explicitly terminate the program with the Exit statement.
  2102.  
  2103.  
  2104.  
  2105.  Goto Statements
  2106. -----------------
  2107.  
  2108. The "goto" statement immediately transfers execution to a defined
  2109. label.  It should be used with extreme care, and if possible
  2110. avoided.  Its form is:
  2111.  
  2112. <Goto Statement> ::= goto <Identifier>
  2113.  
  2114. Standard Pascal requires that a goto label should be a series of
  2115. digits, and Turbo Pascal extends that definition to allow
  2116. identifiers to be used as labels.  PCQ Pascal takes the next
  2117. logical step by requiring that labels be identifiers, not numbers.
  2118.  
  2119. Most programmers will tell you that the "goto" statement is simply
  2120. bad programming practice, because it makes programs difficult to
  2121. understand and debug.  There are, however, other problems.  For
  2122. instance, if you "goto" from inside a "for" loop to outside of the
  2123. loop, you will confuse your program's stack (until you leave the
  2124. routine).  Similar things happen for the "with" statement.  I
  2125. won't even bother to tell you the havoc that would ensue if you
  2126. jumped into a "for" loop from outside.
  2127.  
  2128. The moral of the story is: try to avoid them.
  2129.  
  2130.  
  2131.  
  2132.  
  2133.  
  2134.  
  2135. ===================================================================
  2136.  
  2137.                       Input/Output
  2138.  
  2139. ===================================================================
  2140.  
  2141.  
  2142.  Pascal IO
  2143. -----------
  2144.  
  2145. You can think of the Pascal IO routines as an interface to the
  2146. AmigaDOS routines.  The Pascal IO routines all use AmigaDOS for
  2147. the actual reading and writing, so if you felt like it you could
  2148. just use an AmigaDOS file instead.
  2149.  
  2150. Pascal IO does have several advantages, however.  First of all,
  2151. all PCQ Pascal files are buffered, which means that reads and
  2152. writes do not necessarily have to access AmigaDOS each time.  That
  2153. speeds things up a bit.
  2154.  
  2155. The other advantage you get is the use of the Pascal Read, ReadLn,
  2156. Write and Writeln routines, which can be awfully handy.
  2157.  
  2158. When you declare a file in your program, as either a "File of Some
  2159. Type" or as "Text", you are in effect allocating a record.  That
  2160. record, if its fields were accessible, would look like:
  2161.  
  2162.      PCQFile = record
  2163.          Handle      : An AmigaDOS file handle
  2164.          Next        : A pointer to the next open Pascal file
  2165.          Buffer      : The address of the file's buffer
  2166.          Current     : The position in the buffer at which the
  2167.                        next read or write will take place.
  2168.          Last        : The Last position of a read
  2169.          Max         : The address of the end of the buffer+1
  2170.          RecSize     : The size of the file elements
  2171.          Interactive : A Boolean value - True means the file
  2172.                        is attached to a CLI window.
  2173.          EOF         : A Boolean value
  2174.          Access      : A Short value, either MODE_NEWFILE or
  2175.                        MODE_OLDFILE
  2176.      end;
  2177.  
  2178.  
  2179.  
  2180.  Text and Typed Files
  2181. ----------------------
  2182.  
  2183. Pascal has two very different types of files.  The normal kind of
  2184. file is called a typed file, and is declared with a type
  2185. specification of the form:
  2186.  
  2187.                   FileVar : File of ElementType
  2188.  
  2189. Typed files are essentially unlimited sequences of elements of
  2190. that one element type.  The Write command can be used to write
  2191. individual elements to the end of the file, and the Read command
  2192. can be used to input the current element and move the file pointer
  2193. to the next one.  You can only write one type of element to each
  2194. typed file.
  2195.  
  2196. Typed files store their elements in exactly the same format that
  2197. they appear in memory, so they are often unreadable.  A file of
  2198. character elements is readable, but a file of integer elements
  2199. would be incomprehensible.  Since typed files always store
  2200. complete elements, each element is necessarily a fixed size.
  2201.  
  2202. You don't actually need anything but typed files - anything you
  2203. can do with Pascal files can be done with them.  For the sake of
  2204. convenience, however, Pascal also uses the Text file type.  The
  2205. Text file is a special kind of "File of Char", but is not
  2206. compatible with it.  Text files are made up of ASCII characters
  2207. broken up into variable length lines.  Each line is terminated by
  2208. a special newline character, which on the Amiga is the line feed
  2209. character (ASCII 10.  On MS-DOS machines, the newline character is
  2210. the carriage return/line feed sequence).
  2211.  
  2212. Since Text files (like this documentation, and all the source
  2213. files) are so common, Pascal has a variety of routines built-in to
  2214. read and write values to and from them.  Most of the standard
  2215. types, for example, have a special routine for converting them
  2216. into ASCII characters and writing them to a file.  These routines
  2217. are called automatically by the compiler to write each expression
  2218. in a Write procedure to a Text file.  Similar routines exist for
  2219. reading the same types.  The descriptions of the Read and Write
  2220. procedures below described exactly how this conversion takes
  2221. place.
  2222.  
  2223. There is even a special form of the Read and Write procedures
  2224. designed to work only with Text files - the ReadLn and WriteLn
  2225. commands.  They are explained below, but note that since typed
  2226. files have no lines, these two routines are used only for Text
  2227. files.
  2228.  
  2229.  
  2230.  Opening Files
  2231. ---------------
  2232.  
  2233. There are several closely related routines for opening Pascal
  2234. files.  For opening input files, which are existing files that
  2235. will be opened for reading, you can use either the ReOpen()
  2236. function or the Reset() procedure.  They are defined as follows:
  2237.  
  2238.  
  2239.  
  2240.                Reset(var FileVar : File or Text;
  2241.                         FileName : String;
  2242.                       BufferSize : Integer);
  2243.  
  2244. The "Reset" procedure opens a file for reading.  The FileVar
  2245. parameter specifies the Pascal file variable that should be
  2246. associated with this AmigaDOS file.  The FileName is the file
  2247. name, with a complete path if necessary.  Since this can be any
  2248. valid AmigaDOS filename, it can actually refer to the printer, a
  2249. console window, or all sorts of other things.
  2250.  
  2251. The BufferSize parameter specifies the size of the buffer you
  2252. want, in bytes.  When PCQ tries to open your file, it will try to
  2253. allocate this much memory as a buffer.  If it can't, it sets
  2254. IOResult and fails.  Actually, PCQ tries to allocate a buffer that
  2255. is an even multiple of the file element size, not larger than
  2256. BufferSize, but at least one element long (the element size for
  2257. Text files is one character).  The BufferSize parameter is
  2258. entirely optional - if it's not included, a default value of 128
  2259. is used.
  2260.  
  2261. If you are using automatic IO checking, your program will abort
  2262. with a runtime error if the file cannot be opened.  If you are
  2263. checking manually, it will just set IOResult.
  2264.  
  2265. The variable FileVar should not refer to an file that's already
  2266. open.  Either the file should be closed first, or you should use a
  2267. different file variable.
  2268.  
  2269.  
  2270.  
  2271.              ReOpen(fname      : String;
  2272.                     var fvar   : file or text;
  2273.                     buffersize : Integer) : Boolean
  2274.  
  2275. ReOpen is the function form of Reset.  It attempts to open a file
  2276. in the same way as Reset, and if everything goes O.K. it returns
  2277. True.  If there was a problem, it returns False.
  2278.  
  2279. ReOpen never sets IOResult, so if you are using automatic IO
  2280. checking a call to ReOpen will not abort the program.  As in the
  2281. Reset procedure, the BufferSize parameter is optional.
  2282.  
  2283.  
  2284.  
  2285. If you need to open a file for writing (which deletes any existing
  2286. file of the same name!), you can use the Rewrite procedure or the
  2287. Open() function.  They are defined as:
  2288.  
  2289.  
  2290.  
  2291.              Rewrite(var FileVar : File or Text;
  2292.                         FileName : String;
  2293.                       BufferSize : Integer);
  2294.  
  2295. Rewrite opens an AmigaDOS file for writing, erasing any existing
  2296. file with the same name.  The parameters are just like the Reset
  2297. command, and the BufferSize is still optional.
  2298.  
  2299. Rewrite sets IOResult, so if your program is using automatic IO
  2300. checking it will abort if the file cannot be opened.  Programs
  2301. handling their own IO checks should be sure to look at IOResult.
  2302.  
  2303. As with all the file opening routines, you should not use a file
  2304. variable that already refers to an open file.
  2305.  
  2306.  
  2307.  
  2308.                Open(fname      : String;
  2309.                     var fvar   : file or text;
  2310.                     buffersize : Integer) : Boolean
  2311.  
  2312. Open is equivalent to Rewrite, but in function form.  It attempts
  2313. to open the file for writing, and if everything goes O.K.  it
  2314. returns True.  If there is any problem, it returns false.
  2315. Remember that opening a file for output means that any existing
  2316. file with the same name gets erased.
  2317.  
  2318. Open does not set IOResult, so programs using automatic IO
  2319. checking can use it without aborting.  The BufferSize parameter,
  2320. just as in the rest of the file opening routines, is optional.
  2321.  
  2322.  
  2323.  
  2324.  Writing to Files
  2325. ------------------
  2326.  
  2327. Output in Pascal is handled by the Write and Writeln procedures.
  2328. Unlike most Pascal procedures, these routines will accept an
  2329. unlimited number of parameters.  If you are writing to a Text
  2330. file, the parameters can be a variety of types.  The Write
  2331. procedure has the following basic form:
  2332.  
  2333.  
  2334.      Write(var FileVar : Text or Typed File, Expressions...)
  2335.  
  2336. The FileVar is optional.  If it is not included, the standard Text
  2337. file Output is used in its place.  If the FileVar is a typed file,
  2338. each expression must be of the element type.  They will be written
  2339. to the file with no space in between them, formatted just as they
  2340. are in memory.
  2341.  
  2342. If you are writing to a text file, it's a different story
  2343. entirely.  First of all, each expression can take the form "e:m:n"
  2344. where e is the expression itself and m and n are constant
  2345. integers.  m specifies the minimum field width - if the item to be
  2346. written would take up fewer than m characters, spaces are written
  2347. to fill out the field.  n is only allowed if e is an expression of
  2348. type Real, and it specifies how many digits to the right of the
  2349. decimal point will be written out.  The default values for m and n
  2350. are 1 and 2, respectively.  Specifically what gets written out
  2351. depends on the type, according to the following:
  2352.  
  2353. Integer
  2354. Short
  2355. Byte     These three types are all written as sequences of ASCII
  2356.          digits, as expected.  They are not preceded by any spaces,
  2357.          but Short and Integer types might lead off with a minus
  2358.          sign if appropriate.  There will be no trailing spaces.
  2359.  
  2360. Real     The entire integer part (the part to the left of the
  2361.          decimal point) is written out.  If n is not zero, a
  2362.          decimal point followed by n fractional digits are written
  2363.          out.  Note that for Real numbers, m indicates the number
  2364.          of digits to the left of the decimal point that should be
  2365.          written, not the full field width (this will probably
  2366.          change in the next version).
  2367.  
  2368. Char     A character is written out as just the single character,
  2369.          unchanged.
  2370.  
  2371. Array of Char
  2372.          The entire array, for its whole declared length, is
  2373.          written out character by character.
  2374.  
  2375. String   The entire string up to, but not including, the
  2376.          terminating null character is written.
  2377.  
  2378. Boolean  Either the word TRUE or the word FALSE is written, with
  2379.          no leading or trailing spaces.
  2380.  
  2381.  
  2382.  
  2383.            WriteLn(var FileVar : Text; Expressions...)
  2384.  
  2385. Writeln is exactly the same as Write, but after is has written out
  2386. each of the expressions according to the rules above, it also
  2387. writes out a newline character.  WriteLn can only be used on Text
  2388. files.
  2389.  
  2390.  
  2391.  Reading from Files
  2392. --------------------
  2393.  
  2394. Input in Pascal is handled by the Read procedure.  Like the Write
  2395. procedures, Read accepts any number of parameters, and many types
  2396. of parameters if you are reading from a Text file.  The format is
  2397. as follows:
  2398.  
  2399.    Read(var FVar : Text or Typed File; Variable References....)
  2400.  
  2401. The FVar parameter is optional.  If it is omitted, the standard
  2402. Text file "Input" is used in its place.
  2403.  
  2404. If FVar refers to a typed file, each variable reference is filled
  2405. with the subsequent file elements, unless EOF is reached or some
  2406. other error occurs first.  Reading from a Text file is a somewhat
  2407. more flexible job.  Just as with the Write statements, what
  2408. happens depends on the type being read, according to the
  2409. following:
  2410.  
  2411. Integer
  2412. Short
  2413. Byte     All white space, which is defined as any character whose
  2414.          ASCII value is less than or equal to 32 (the space
  2415.          character) is skipped.  If the first non-white space
  2416.          character is not a digit or the EOF is reached, an IO
  2417.          error is raised (see Exit Procedures for more
  2418.          information).  If not, digits are read until the first
  2419.          non-digit.  The resulting number is returned, and the
  2420.          file pointer rests on that non-digit.
  2421.  
  2422. Real     First, an integer is read exactly as above.  If the next
  2423.          character is a period, digits are again read in as
  2424.          fractional digits until the first non-digit.  The pointer
  2425.          rests on that first non-digit.  A Real value does not
  2426.          need a fractional part, nor does it require a decimal 
  2427.          point.
  2428.  
  2429. Char     Reads the next single character.  Standard Pascal
  2430.          translates end-of-line characters into spaces, but PCQ
  2431.          Pascal, like Turbo Pascal, allows them to come through as
  2432.          ASCII linefeeds.
  2433.  
  2434. Array of Char
  2435.          Reads characters into the array until either the array is
  2436.          full, or the end-of-line is reached.  If the end-of-line
  2437.          is reached, the rest of the array is padded with spaces
  2438.          and the file pointer is left pointing at the end-of-line
  2439.          character - you'll need to call Readln to get rid of it.
  2440.  
  2441. String   Reads characters into the String buffer until the
  2442.          end-of-line is reached.  At that point the string is
  2443.          terminated by a zero byte, and the file pointer is left
  2444.          pointing to the end-of-line character.  Note that this
  2445.          routine does not check for length, so you need to be sure
  2446.          to provide a large enough string for the file you are
  2447.          reading.
  2448.  
  2449. Boolean  Can't be done.
  2450.  
  2451.  
  2452. A series of variable references in a Read procedure acts exactly
  2453. like each of the references in individual Read procedures.  Thus:
  2454.  
  2455.                      Read(Input, Var1, Var2);
  2456.  
  2457. is equivalent to:
  2458.  
  2459.               Read(Input, Var1); Read(Input, Var2);
  2460.  
  2461. which is also equivalent to:
  2462.  
  2463.                      Read(Var1); Read(Var2);
  2464.  
  2465.  
  2466.  
  2467.          ReadLn(var FVar : Text; Variable References...)
  2468.  
  2469. Readln is exactly like Read, but after all the specified variables
  2470. have been read, this command eats characters until it finds the
  2471. next end-of-line, and it eats that too.  This command can only be
  2472. used on Text files.
  2473.  
  2474.  
  2475.  File Buffers
  2476. --------------
  2477.  
  2478. Like Standard Pascal, but unlike Turbo Pascal, PCQ allows you to
  2479. access the file buffer directly.  The syntax of the reference
  2480. looks like:
  2481.  
  2482.                    <File Variable Reference> ^
  2483.                           e.g. FileVar^
  2484.  
  2485. That expression has the same type as the elements of the file
  2486. itself (Text files have Char elements).  With input files, this
  2487. syntax looks at the next element that will be input by the Read()
  2488. procedure, like a look-ahead.  If EOF(FileVar) is True, then
  2489. FileVar^ is invalid.
  2490.  
  2491. For output files, the file buffer reference shows you the output
  2492. buffer.  This is not the value that will be written out with the
  2493. Write() procedure - see the description of Put() below for more
  2494. information.
  2495.  
  2496. Logically, the file buffer you access through this syntax is only
  2497. as long as one element, but the actual buffer in memory can be of
  2498. virtually any size.  See the file opening commands for information
  2499. on setting the buffer size.
  2500.  
  2501. Using this syntax in PCQ is actually considered an IO operation,
  2502. in the sense that it can set IOResult.  This only occurs when the
  2503. file is interactive, because the buffers of interactive files are
  2504. not kept full.
  2505.  
  2506. If you are making use of the file buffer, you will probably use on
  2507. or both of the following routines:
  2508.  
  2509.  
  2510.               Get(var FileVar : Text or Typed File)
  2511.  
  2512. Get just moves the file pointer from the current element to the
  2513. next one.  That may involve calling DOS to refill the buffer, but
  2514. normally it's just a matter of adjusting a field in the file
  2515. variable itself.  It is an error to call this routine on a file
  2516. for which EOF(FileVar) is True.
  2517.  
  2518. Every read from a typed file of the form "Read(FVar,Element)" can
  2519. be thought of as:
  2520.  
  2521.         Element := FVar^; { To assign the current value }
  2522.         Get(FVar);        { To advance the file pointer }
  2523.  
  2524.  
  2525.               Put(var FileVar : Text or Typed File)
  2526.  
  2527. Put moves the file pointer past the current element in an output
  2528. file, writing the buffer to disk if necessary.  Every statement of
  2529. the form "Write(FVar,Expr)", where FVar is a typed file, could be
  2530. implemented as:
  2531.  
  2532.         FVar^ := Expr; { Set the buffer value }
  2533.         Put(FVar);     { Commit the buffer    }
  2534.  
  2535. Note that until the Put procedure is called, any assignments to
  2536. the file buffer will write over each other.
  2537.  
  2538.  
  2539.  IO Checking
  2540. -------------
  2541.  
  2542. Input & Output can cause more unforeseen errors than virtually any
  2543. other area of programming.  PCQ Pascal catches IO errors in one of
  2544. two ways.  The first is called automatic IO checking - PCQ checks
  2545. for errors after each and every IO operation.  If there is an
  2546. error, the program aborts with a runtime error.  Believe it or
  2547. not, that's the default behavior.
  2548.  
  2549. If you turn off automatic checking using the {$I-} compiler
  2550. directive, you become responsible for checking for errors.  You do
  2551. this by calling the IOResult function, which returns 0 if
  2552. everything is O.K., or some other number if there was a problem.
  2553. When you call IOResult, you automatically clear its value, so if
  2554. you are going to use the error code later on you need to save it
  2555. in a variable.
  2556.  
  2557. IOResult is set by every IO routine.  No IO routines will function
  2558. if IOResult is not zero, so you should check for errors whenever
  2559. possible to avoid skipping reads and writes.
  2560.  
  2561. The values returned by IOResult are the same as the runtime
  2562. errors - possible values are listed in the section called Exit
  2563. Procedures.
  2564.  
  2565.  
  2566.  Standard IO
  2567. -------------
  2568.  
  2569. One of the tricky parts of programming on the Amiga is that a
  2570. program can be launched from two very different environments.  The
  2571. CLI invokes a program in much the same way as MS-DOS does - the
  2572. program has obvious input and output channels.  The Workbench, on
  2573. the other hand, offers nothing of the sort.  A program that needs
  2574. input and output channels must establish them explicitly.
  2575.  
  2576. All PCQ Programs establish some sort of standard input and output
  2577. channels, which are accessed through the Text files Input and
  2578. Output.  What those files represent depends, naturally, on the
  2579. environment from which the program was executed.
  2580.  
  2581. Let's take the simple case first.  If you run a program from the
  2582. CLI, Input and Output will refer to the CLI window itself.  Unless
  2583. you use indirection, that is, in which case Input and Output will
  2584. refer to the channels specified on the command line (see an
  2585. AmigaDOS manual for more information).  Maybe that wasn't so
  2586. simple after all.
  2587.  
  2588. If the program was launched from the Workbench, the startup code
  2589. goes through several steps to establish Input and Output.  First
  2590. of all, it looks at the value of the standard String typed
  2591. constant StdInName.  If StdInName is Nil, no file is opened and
  2592. referring to Input will cause grave problems.  If not, the startup
  2593. code attempts to open the file.  If it can't do it, it terminates
  2594. with run-time error 53.  If all went well, Input is established.
  2595.  
  2596. Next the startup code looks at StdOutName.  If it's Nil, Output is
  2597. not established, so any Write procedures had better use an
  2598. explicit file.  If StdOutName refers to the same string as
  2599. StdInName (not two strings with the same contents - it actually
  2600. has to point to the same memory), and if the file associated with
  2601. Input is interactive (i.e.  attached to a console window), then
  2602. Output is associated with the same file handle as Input.  The
  2603. default values of StdInName and StdOutName have this property.  If
  2604. either of those tests fail, the startup code tries to open a file
  2605. according to StdOutName, and if it works, then Output is set up
  2606. accordingly.  Otherwise, the program will terminate with runtime
  2607. error 57.
  2608.  
  2609. The default values for the two channels are defined in PCQ.lib as
  2610. follows:
  2611.  
  2612.         CONST
  2613.             StdInName  : String = "CON:0/0/640/200/";
  2614.             StdOutName : String = StdInName;
  2615.  
  2616. According to the rules specified above, this would normally result
  2617. in one full-screen console window being opened, with input coming
  2618. from it and output going to it.
  2619.  
  2620. Note that StdInName and StdOutName are defined as typed constants.
  2621. They can't be variables, because they are opened before any of
  2622. your code executes.  If that's a major problem, you can define
  2623. them both as Nil, and from inside your program you can open Input
  2624. and Output as anything you like.  You should probably re-use Input
  2625. and Output only when your program was run from the Workbench (you
  2626. can check if you were run from the Workbench by calling
  2627. GetStartupMsg from "Utils/Parameters.i").
  2628.  
  2629. If you compiled your program using the "-s" small initialization
  2630. code switch, all bets are off:  Input and Output are not
  2631. established, and in fact none of the other IO routines are
  2632. initialized either.  See the section called Small Initialization
  2633. Code for more information.
  2634.  
  2635.  
  2636.  
  2637.  
  2638.  
  2639. ===================================================================
  2640.  
  2641.                            Strings
  2642.  
  2643. ===================================================================
  2644.  
  2645. PCQ Pascal strings are similar to C strings, and nothing at all
  2646. like Turbo Pascal strings.  That's too bad, because Turbo Pascal
  2647. strings are a lot easier to work with.  Eventually, PCQ Pascal
  2648. strings will be the same as Turbo Pascal strings, but that day has
  2649. yet to come.
  2650.  
  2651. The string type can be thought of as simply "^Char".  Thus all
  2652. string variables take up exactly 4 bytes, and they store the
  2653. address of the actual text.  The text can be of any length, and
  2654. is terminated by the character Chr(0).  A statement like:
  2655.  
  2656.         StringVar := "A String"
  2657.  
  2658. ... actually stores the address of the constant string in the
  2659. string variable, rather than copying the string itself into some
  2660. existing space.
  2661.  
  2662. String constants in the Pascal text are delimited by double quote
  2663. characters, as opposed to the single quote characters of character
  2664. array constants.  Thus "A String" is considered a constant of type
  2665. String, whereas 'not a string' is considered a constant of type
  2666. "Array [0..11] of Char".
  2667.  
  2668. Strings are defined as simple pointers, so the reference
  2669. "StringVar^" is valid, and is of type Char.  It actually points to
  2670. the first byte within the string buffer.  But unlike normal
  2671. pointers, the individual characters in a string can also be
  2672. accessed through subscript notation.  For example, to get the
  2673. fourth character in a string, you could use "StringVar[3]".
  2674. Remember that "StringVar[0]" is the first element.
  2675.  
  2676.  
  2677.  Allocating String Space
  2678. -------------------------
  2679.  
  2680. Since the actual String variables only store an address, you need
  2681. to allocate some space for the actual text.  C allows you define
  2682. that space when you declare the string type, but PCQ Pascal
  2683. doesn't even offer that much.  In PCQ Pascal, you have to
  2684. explicitly allocate the memory from the system, or assign the
  2685. address of a buffer variable to the string.  There are several
  2686. functions, all defined in the include file StringLib.i, that
  2687. allocate space for strings.  They are:
  2688.  
  2689.                AllocString(Size : Integer) : String
  2690.  
  2691. AllocString simply returns an uninitialized memory area that is at
  2692. least Size bytes long.  This memory is considered PCQ memory, so
  2693. it is returned to the system after its use (see the section called
  2694. Memory Management for more information).
  2695.  
  2696.                 strdup(InString : String) : String
  2697.  
  2698. The strdup (string duplicate) function is equivalent to the
  2699. following:
  2700.                 temp := AllocString(strlen(InString));
  2701.                 strcpy(temp,InString);
  2702.                 strdup := temp;
  2703.  
  2704. In other words, it allocates just enough memory to hold the input
  2705. string, then makes a copy of the input string in the new buffer.
  2706. This memory is also considered PCQ memory, so it will be returned
  2707. to the system when the program terminates.
  2708.  
  2709. The other way to set up a string buffer is to assign the string
  2710. variable the address of an array declared elsewhere.  Thus the
  2711. following:
  2712.  
  2713.         Var
  2714.             String1 : String;
  2715.             Buffer1 : Array [0..127] of Char;
  2716.         begin
  2717.             String1 := Adr(Buffer1);
  2718.  
  2719. ... sets up a 128-character buffer for String1.  If you try to
  2720. store a 129-character string in that buffer, all sorts of problems
  2721. will result, so take care.
  2722.  
  2723.  
  2724.  Using Escape Characters
  2725. -------------------------
  2726.  
  2727. There are, of course, lots of useful characters that can't easily
  2728. be written into a program source file.  The end-of-line character,
  2729. for example, is always considered the end of a line, rather than
  2730. taken as a constant.  If you need to include this sort of
  2731. character in any text constant (a Char, Array of Char, or String),
  2732. you use the C escape convention, in which a backslash "\" is
  2733. followed by a special character.  The escape sequences supported
  2734. by PCQ are:
  2735.  
  2736.            \n   Line Feed, chr(10)
  2737.            \t   Tab, chr(9)
  2738.            \0   Null, chr(0)
  2739.            \b   Backspace, chr(8)
  2740.            \e   ESC, chr(27)
  2741.            \c   CSI (Control Sequence Introducer), chr($9B)
  2742.            \a   Attention, chr(7)
  2743.            \f   Form Feed, chr(12)
  2744.            \r   Carriage Return, chr(13)
  2745.            \v   Vertical Tab, chr(11)
  2746.  
  2747. Every other character passes through unchanged, so the following
  2748. definitions also hold:
  2749.  
  2750.            \\   Just a single backslash
  2751.            \'   A single quote, even in a single-quote-delimited
  2752.                 constant
  2753.            \"   A double quote, even in a String constant
  2754.  
  2755. Thus a string like "A\tboy\nand\\his \"dog." becomes:
  2756.  
  2757.         |A      boy
  2758.         |and\his "dog
  2759.  
  2760. ... where the vertical bar | represents the left margin.
  2761.  
  2762.  
  2763.  StringLib
  2764. -----------
  2765.  
  2766. StringLib.i is an include file in the Utils directory that defines
  2767. a bunch of C-style functions for use on strings.  Those functions
  2768. are explained in the include file itself.  The source for these
  2769. routines is in the runtime library source, which is available by
  2770. request.
  2771.  
  2772.  
  2773.  
  2774.  
  2775. ===================================================================
  2776.  
  2777.                         Memory Management
  2778.  
  2779. ===================================================================
  2780.  
  2781. One of the problems with Amiga programming is that there is no
  2782. resource tracking.  In an MS-DOS program, you can open files and
  2783. allocate memory like crazy, then just quit the program and
  2784. everything's O.K.  On the Amiga, all those files would stay open
  2785. and the memory would stay allocated.  You are expected to clean up
  2786. after yourself.
  2787.  
  2788. To help you do that, PCQ Pascal uses a special memory allocation
  2789. scheme that uses the Intuition AllocRemember routine to keep track
  2790. of all your memory allocations.  When your program terminates, any
  2791. memory you haven't deallocated is automatically freed by an exit
  2792. procedure.
  2793.  
  2794. This only works for memory allocated through one of the special
  2795. PCQ routines New, AllocString (from Utils/StringLib.i) or GetMem
  2796. (from Utils/PCQMemory.i).  Memory allocated through one of these
  2797. routines is called PCQ memory, but of course it's no different
  2798. from normal system memory except that it will be returned.
  2799.  
  2800. Even though it will be automatically freed, you should deallocate
  2801. memory as soon as you are through with it.  There might be other
  2802. programs running that can use it.  If you do free PCQ memory, you
  2803. need to use Dispose, FreeString or FreePCQMem to do it.  If you
  2804. don't, the memory will be returned to the system, but the PCQ
  2805. memory routines won't know about it.  They will, therefore, try to
  2806. free it again when the program terminates.  Guru.
  2807.  
  2808. PCQ memory is always allocated with the flags MEMF_PUBLIC and
  2809. MEMF_CLEAR.  If you need chip memory, therefore, you should use
  2810. the normal Exec function AllocMem (from Exec/Memory.i).
  2811.  
  2812.  
  2813.  HeapError
  2814. -----------
  2815.  
  2816. So what happens when the PCQ memory routines are unable to
  2817. allocate some memory a user has called for?  That depends on the
  2818. value of HeapError, a standard Address variable.  HeapError
  2819. contains the address of a function that has a header with the
  2820. following form:
  2821.  
  2822.            Function HeapFunc(Size : Integer) : Integer;
  2823.  
  2824. The Size parameter is the amount of memory the allocator was
  2825. trying to get, and the integer returned determines how the
  2826. allocator will respond to the problem.  If it returns 0, the
  2827. allocator will abort the program with runtime error 54.  If it
  2828. returns 1, the allocator will return the value Nil, so you'll have
  2829. to check after each call to New, AllocString or GetMem for a Nil
  2830. value.  If the HeapError function returns 2, the allocator tries
  2831. the allocation again.  This gives you a chance to free up some
  2832. memory, if possible.  If that allocation fails, the HeapError
  2833. function will get called again.
  2834.  
  2835. To install a function as the HeapError function, you would use
  2836. something like the following:
  2837.  
  2838.                      HeapError := @HeapFunc;
  2839.  
  2840. ... where HeapFunc is defined as above.
  2841.  
  2842.  
  2843.  
  2844.  
  2845. ===================================================================
  2846.  
  2847.                          Exit Procedures
  2848.  
  2849. ===================================================================
  2850.  
  2851. Exit procedures are routines that you set up to run after the main
  2852. routine is finished, or if there is a run-time error.  They are
  2853. used to return resources to the system, or to exit gracefully or
  2854. even recover from run-time errors.
  2855.  
  2856. How it works is:  when a program terminates, for whatever reason,
  2857. PCQ examines the value of ExitProc, a standard Address variable.
  2858. If it is non-nil, PCQ sets ExitProc to Nil and calls the procedure
  2859. it pointed to.  When the procedure returns, PCQ checks ExitProc
  2860. again, and continues calling exit procedures until ExitProc is
  2861. Nil.  The normal PCQ initialization code sets up an exit procedure
  2862. that frees all memory allocated through New or AllocString, and
  2863. closes any Pascal files that remain open.  Normal programs,
  2864. therefore, have at least one exit procedure.
  2865.  
  2866. To make a procedure an exit procedure, first define a routine with
  2867. no parameters.  Then you set the ExitProc standard variable to the
  2868. address of your routine.  In most cases you'll want to save the
  2869. previous value of ExitProc so all the other exit procedures can
  2870. run as well.  Within the exit procedure itself, you should reset
  2871. ExitProc to point to the previous routine.
  2872.  
  2873. There are two additional variables associated with exit procedures
  2874. that are only valid while the procedure is actually running as an
  2875. exit procedure.  They always exist, but their value is only set
  2876. when the program terminates.  They are:
  2877.  
  2878. ExitCode     ExitCode contains the value of any runtime error that
  2879.              caused the program termination.  This is either a
  2880.              value you supplied through the Exit() routine, or a
  2881.              runtime error code.
  2882.  
  2883. ExitAddr     ExitAddr is the address where a runtime error
  2884.              occurred.  It is only valid when ExitCode is non-zero.
  2885.              It can (in theory) be used to recover from a runtime
  2886.              error, but you'd have to be awfully familiar with the
  2887.              actual runtime code to get it to work.  Of course you
  2888.              can get the runtime source from me.
  2889.  
  2890.  
  2891.  Runtime Errors
  2892. ----------------
  2893.  
  2894. There are several errors that will cause a PCQ program to
  2895. immediately terminate.  When that happens, ExitCode will be set to
  2896. a specific value, which will eventually be returned to AmigaDOS.
  2897. AmigaDOS, in turn, will normally ignore it, so you'll never see
  2898. it.  The two ways I know of the see the return value (if it is
  2899. non-zero) are to run the program in a script, or to run the
  2900. program using AmigaDOS's Run command.  In either case, if the
  2901. program has a non-zero return code AmigaDOS will write out
  2902. "ProgramName failed returncode #".
  2903.  
  2904. The runtime errors generated by PCQ programs are as follows:
  2905.  
  2906.  
  2907.             Code       Description
  2908.           ----------------------------------------------
  2909.              50    No memory for IO buffer (1)
  2910.              51    Read past EOF (1)
  2911.              52    Input file not open (2)
  2912.              53    Could not open StdInName (3)
  2913.              54    New() failed (4)
  2914.              55    Integer divide by zero
  2915.              56    Output file not open (2)
  2916.              57    Could not open StdOutName (3)
  2917.              58    Found EOF before first digit while
  2918.                    reading an integer (1)
  2919.              59    No digits found in reading an integer (1)
  2920.              60    Range error (5)
  2921.  
  2922.         The following AmigaDOS error codes can result from a call
  2923.         to Open, ReOpen, Write, Read, etc:  (1)
  2924.  
  2925.             103    Insufficient free store
  2926.             202    Object in use
  2927.             203    Object already exists
  2928.             204    Directory not found
  2929.             205    Object not found
  2930.             206    Invalid window specification
  2931.             210    Invalid component name
  2932.             212    Object wrong type
  2933.             213    Disk not validated
  2934.             214    Disk write protected
  2935.             218    Device not mounted
  2936.             221    Disk full
  2937.             223    File is write protected
  2938.             224    File is read protected
  2939.             225    Not a DOS disk
  2940.             226    No disk in drive
  2941.  
  2942.         (1)  These errors only cause runtime errors when automatic
  2943.              IO error checking is enabled (it's the default).  If
  2944.              you have used the {$I-} directive to indicate that
  2945.              you'll check IOResult explicitly, the program will
  2946.              not automatically terminate.
  2947.         (2)  PCQ cannot always determine when the file is not
  2948.              open.  If it can, it issues this error.  If it can't,
  2949.              the machine will crash.
  2950.         (3)  These errors occur in the initialization code, before
  2951.              any exit procedures are established.
  2952.         (4)  See the section called Memory Management to see how
  2953.              keep a runtime error from being issued.
  2954.         (5)  This only occurs if you have turned range checking on
  2955.              with the {$R+} directive.
  2956.  
  2957.  
  2958.  
  2959.  
  2960.  
  2961. ===================================================================
  2962.  
  2963.                        Compiler Directives
  2964.  
  2965. ===================================================================
  2966.  
  2967. There are several options that PCQ Pascal provides that are not
  2968. useful for all programs.  For example, a large application should
  2969. not terminate with a runtime error if it can't open a file.
  2970. Therefore PCQ Pascal allows you to determine several aspects of
  2971. the program generated from your code.
  2972.  
  2973. You control these options by issuing compiler directives.
  2974. Compiler directives are contained in comments, and must begin with
  2975. a dollar sign "$" as the first character in the comment.
  2976. Immediately following the dollar sign is a letter indicating the
  2977. directive, which is then followed by zero or more characters
  2978. giving additional information.
  2979.  
  2980. You can include more than one directive in a single comment by
  2981. separating the directives by commas.  Thus the following
  2982. directives turn IO checking off, and range checking on:
  2983.  
  2984.                              {$I-,R+}
  2985.  
  2986. The following directives are supported:
  2987.  
  2988.              {$A Any number of assembly instructions}
  2989.  
  2990. The $A directive allows you to insert assembly language
  2991. instructions into the source code at the given point.  The text of
  2992. the instructions is passed through to the assembler unchanged, so
  2993. you should include comments and make variable references according
  2994. to assembly language style.
  2995.  
  2996. Since comments are allowed anywhere that white space is allowed,
  2997. you could technically insert some assembly language instructions
  2998. in the middle of an expression.  That could produce unpredictable
  2999. results, however, so you should use assembly language only between
  3000. statements.
  3001.  
  3002.                           {$B+} or {$B-}
  3003.  
  3004. The $B directive turns short-circuit evaluations on and off.  If
  3005. you use the $B+ directive to turn short-circuit evaluations on,
  3006. which is actually the default, PCQ will evaluate Boolean
  3007. expressions normally, but as soon as the final value of the
  3008. expression is known, it will skip any remaining parts of the
  3009. expression.  Thus in a series of "and" clauses, as soon as one of
  3010. them evaluates to False, the rest are not evaluated at all.  In a
  3011. series of "or" clauses, as soon as one of them evaluates to True,
  3012. the rest are skipped.  If you are using short-circuit evaluations
  3013. the expression will always be evaluated from left to right.
  3014. Short-circuits make Boolean evaluation somewhat faster, especially
  3015. in long equations.
  3016.  
  3017. If you turn short-circuit evaluations off using the $B- directive,
  3018. all parts of a Boolean expression will be evaluated even if the
  3019. outcome is not in doubt, and the expression will not necessarily
  3020. be evaluated in left-to-right order.
  3021.  
  3022.                            {$I "fname"}
  3023.  
  3024. This directive inserts the file "fname" into the input stream at
  3025. the current position in the file.  When the included file has been
  3026. fully read, the input is again taken from the original file.  You
  3027. can't use any other directives after this one, but you can include
  3028. any comments you like after the file name.
  3029.  
  3030. In order to keep from including a file more than once, the
  3031. compiler keeps a list of all file name already included.  If the
  3032. file name matches one already on the list, it is not included.
  3033. Note that only the actual file name, not the entire path, is
  3034. compared.  Thus you should be sure that all your include files
  3035. have unique names.
  3036.  
  3037. Almost all the example programs demonstrate the use of include
  3038. files.
  3039.  
  3040.                           {$I+} or {$I-}
  3041.  
  3042. The other form of the $I directive determines your programs
  3043. reaction to Input/Output errors.  The default behavior, which
  3044. corresponds to the {$I+} directive, is to issue a runtime error
  3045. whenever an error is detected in an IO routine.  The other option,
  3046. specified by the {$I-} directive, indicates that the program
  3047. itself will check the IOResult function after IO operations, and
  3048. handle any errors accordingly.  See the Input/Output section for
  3049. more information.
  3050.  
  3051.                  {$SN} or {$SX} or {$SP} or {$SD}
  3052.  
  3053. The $S option controls the storage of global variables and typed
  3054. constants.  The N option (for Normal storage) tells the compiler
  3055. that for all subsequent global variables, the compiler should
  3056. allocate memory in the data segment, and also issue an external
  3057. definition (XDEF in assembly language) for the identifier, so it
  3058. can be used by external routines.  This is the normal storage
  3059. scheme for PCQ programs.
  3060.  
  3061. The X option (for eXternal storage) tells the compiler that all
  3062. subsequent global variables are defined outside of the program.
  3063. Therefore the compiler should not allocate any space for the
  3064. variables, but simply create an external reference (XREF in
  3065. assembly language).  This is the normal storage scheme for
  3066. external files.
  3067.  
  3068. The P option (for Private storage) tells the compiler that it
  3069. should allocate space for global variables, but it should not
  3070. export the identifier itself.  This allows external files to have
  3071. global variables that do not affect the main program.
  3072.  
  3073. The D option (for Default storage) resets the storage to its
  3074. standard value.  In an external program, it acts like {$SX}, and
  3075. in a normal program it acts like {$SN}.
  3076.  
  3077.                           {$O+} or {$O-}
  3078.  
  3079. These options are identical to the {$I+} and {$I-} options.
  3080.  
  3081.                           {$R+} or {$R-}
  3082.  
  3083. The $R directive determines whether the compiler will verify that
  3084. index values are within the specified range of the array.  The
  3085. default behavior is {$R-}, which means that the compiler will not
  3086. generate the extra code.  Specifying {$R+} makes the compiler
  3087. issue a runtime error with error code 60.  Turning this option on
  3088. results in larger and slower programs, so I would recommend only
  3089. using the option while testing.
  3090.  
  3091.  
  3092.  
  3093.  
  3094.  
  3095. ===================================================================
  3096.  
  3097.                             Type Casts
  3098.  
  3099. ===================================================================
  3100.  
  3101. If you are using a strongly typed language like Pascal, you need a
  3102. way to get around the type rules.  PCQ Pascal uses the same method
  3103. as Turbo Pascal and Modula-2 to get around the type checks.  The
  3104. format for a type cast is as follows:
  3105.  
  3106.         <Type ID> ( <Expression or Variable Reference> )
  3107.  
  3108. This looks just like a function, but it is definitely not one.  A
  3109. type cast never generates any code - it just lets the code get by
  3110. the compiler.  Naturally, this can lead to some serious problems.
  3111. For example, a type cast like "Short(EnumeratedVar)" will cause
  3112. problems because enumerated types are normally one byte long.  You
  3113. have told the compiler to consider it a two byte value, but the
  3114. other byte is undefined.  The correct way to handle that call
  3115. would be to use the Ord() function, or at least cast it to a Byte
  3116. instead.
  3117.  
  3118. The difference between Short() and Ord() in this example is that
  3119. Ord() is a type transfer function, whereas Short() is not a
  3120. function at all.  As another example, consider the fragment below:
  3121.  
  3122.         Writeln(Integer(2.0));
  3123.         Writeln(Trunc(2.0));
  3124.  
  3125. Those two lines will not write the same values.  Trunc(), another
  3126. type transfer function, converts the real value 2.0 into the
  3127. integer value 2 before writing it.  The Integer "function" does
  3128. nothing at all, so the program just writes the real value as if it
  3129. were an integer, which is sure to produce some preposterous
  3130. number.
  3131.  
  3132. In general, casting an expression to a larger sized expression is
  3133. a bad idea, and casting a simple expression (an ordinal, real, or
  3134. pointer value) to a complex type (an array or record reference) or
  3135. vice versa will almost always produce nonsense results.
  3136.  
  3137.  
  3138.  
  3139. ===================================================================
  3140.  
  3141.                     Small Initialization Code
  3142.  
  3143. ===================================================================
  3144.  
  3145. You might, sometime, want to create a program that doesn't have
  3146. the overhead of normal PCQ Pascal programs.  For example, if you
  3147. never use Pascal files, there's no point having all the code for
  3148. Writeln() in your program.  If you want to cut the start-up and
  3149. shut-down code that PCQ adds to your program to a minimum, you can
  3150. use the "-s" option (for Small) on the command line.  For example,
  3151. to compile Tiny.p with the small startup code, you would use the
  3152. following line:
  3153.  
  3154.         Pascal Tiny.p Tiny.asm -s
  3155.  
  3156. The overhead you get rid of is not useless fat, however, and one
  3157. of the problems with not having it is that you can't use it.  Put
  3158. another way, if you use the "-s" option on the command line, you
  3159. will not be able to use any Pascal IO routines.  Specifically, the
  3160. procedures and functions that become off limits are:
  3161.  
  3162.     Write, WriteLn, Read, ReadLn, Get,
  3163.     Put, Open, ReOpen, Close, IOResult
  3164.  
  3165. The compiler will flag references to all these identifiers with
  3166. the exception of IOResult, but keep in mind that the compiler will
  3167. never see references in separately compiled files (external file)
  3168. or object code libraries.  The moral of this story is that you
  3169. should exercise extreme care when using this option, or you will
  3170. end up linking both startup routines and crashing the machine
  3171. anyway.
  3172.  
  3173. So what, exactly, is missing?  The normal startup code does the
  3174. following:
  3175.  
  3176.     1. Handles the CommandLine or Workbench message.
  3177.     2. Opens Intuition, DOS, and the MathFFP library.
  3178.     3. Sets up Input and Output, opening a window if
  3179.        necessary.
  3180.     4. Initializes the memory allocation list and the
  3181.        open file list so they can be freed at exit.
  3182.     5. Sets up an exit procedure that will free up the
  3183.        memory and files.
  3184.  
  3185. As you can see, there are several pretty big routines: Open(),
  3186. Close(), setting up Input and Output based on the way the program
  3187. was run and the contents of StdInName and StdOutName, the exit
  3188. procedure that frees everything, etc.  The small initialization
  3189. code does this:
  3190.  
  3191.     1. Handles the CommandLine or Workbench message.
  3192.     2. Opens Intuition, DOS and the MathFFP library.
  3193.     3. Intializes the memory list, and sets up a simple
  3194.        routine to free all the New() memory.
  3195.  
  3196. And that's it.  According to my preliminary results, this program:
  3197. "Program Test; begin end." compiles to about 2.5k normally, and
  3198. less than 700 bytes using the small initialization code.
  3199.  
  3200.  
  3201.  
  3202.  
  3203. ===================================================================
  3204.  
  3205.                           External Files
  3206.  
  3207. ===================================================================
  3208.  
  3209. In developing the compiler I found that writing the entire thing
  3210. in one source file was just too much - the intermediate assembly
  3211. files were huge, and the compile times were ridiculous.  In order
  3212. to split things up a bit I added a method for separate
  3213. compilation, similar in purpose to Turbo Pascal's units, but less
  3214. powerful.
  3215.  
  3216. External files have the following format:
  3217.  
  3218.            <External File> ::= External; <Definitions>
  3219.  
  3220. In other words, an external file starts with the reserved word
  3221. External, a semicolon, then any number of definition blocks.
  3222. These definition blocks, as defined above, can be functions,
  3223. procedures, variables, etc.
  3224.  
  3225. Whenever you define a procedure or function, PCQ Pascal "exports"
  3226. the identifier so it can be used by other files.  These other
  3227. files refer to the routine by including an external reference in
  3228. their code (see External References in the Procedures and
  3229. Functions section).  Thus if you define the procedure DoIt in your
  3230. external file, you would include the following declaration in any
  3231. other file in which you used the routine:
  3232.  
  3233.                         Procedure DoIt;
  3234.                             External;
  3235.  
  3236. That declaration tells the compiler that it should "import" the
  3237. identifier from some other file.
  3238.  
  3239. Defining variables and typed constants at the global level in an
  3240. external file is a bit more complicated.  Suppose, for example,
  3241. that you have a global variable in your main program, but you also
  3242. want to refer to it in your external file.  If you declare it
  3243. normally in the external file, you might expect that PCQ would
  3244. reserve two memory areas for the one variable, one in the main
  3245. program and one in the external file.
  3246.  
  3247. Because of that problem, variables and typed constants at the
  3248. global level (only) are by default assumed to be defined only in
  3249. normal program files.  Thus if you define a global variable in an
  3250. external file, PCQ will assume that the variable should be
  3251. imported from some other file, and will not allocate space.  This
  3252. assumption can be overridden by the $S directive, however.
  3253.  
  3254. If you have used an external file, you need to be sure its
  3255. routines are included in the final executable program.  To do
  3256. that, you have to include the file name in the linker command, as
  3257. follows:
  3258.  
  3259.     Blink Main.o Extern1.o ... to MainProgram Library PCQ.lib
  3260.  
  3261. In other words you include any external object files (the output
  3262. of the assembler) in the linker command after the main file, but
  3263. before the "to" keyword.  They can be in any order.
  3264.  
  3265. Although Pascal is a case-insensitive language, assembly is not.
  3266. Thus when you make external references you must be sure that the
  3267. very first reference in your code - either the variable
  3268. declaration or the actual header for the procedure or function -
  3269. has the same case as the definition in the external file.
  3270. Subsequent uses can have any case - the first one is used to
  3271. generate the reference.
  3272.  
  3273.  
  3274.  
  3275.  
  3276. ===================================================================
  3277.  
  3278.                  Notes to Assembly Programmers
  3279.  
  3280. ===================================================================
  3281.  
  3282. In previous versions of the compiler, the registers from d2 to d7,
  3283. a2 and a3 were all available at any time, and the scratch
  3284. registers were available between statements.  That is no longer
  3285. true, so some assembly routines might have to be rewritten.
  3286.  
  3287. Version 1.2 of PCQ now uses registers much more efficiently, which
  3288. means that all of the data registers can be put to use.  PCQ
  3289. allocates registers from d7 down to hold subexpression results, so
  3290. the availability of registers within expressions depends on the
  3291. Pascal code.  Between statements, all data registers are once
  3292. again available.
  3293.  
  3294. Address registers are used as before: a7 is the stack pointer, a6
  3295. is used to point to the library base, a5 points to the stack
  3296. frame, and a4 is used to point to previous frames.  The compiler
  3297. can use a3 and a2 during expressions to hold intermediate address
  3298. values.
  3299.  
  3300. The system routines consider d0,d1,a0 and a1 as scratch, but
  3301. preserve all other registers.
  3302.  
  3303.  
  3304.  
  3305.  
  3306.  
  3307. ===================================================================
  3308.  
  3309.                               Errors
  3310.  
  3311. ===================================================================
  3312.  
  3313. When the compiler runs across some sort of error in your program,
  3314. it prints out the current and previous lines, with the general
  3315. area of the error highlighted.  On the next line, it tells you the
  3316. line number and current procedure or function being defined, plus
  3317. some (hopefully) descriptive text.
  3318.  
  3319. The first error is normally fairly accurate.  After that, however,
  3320. the compiler might start coming up with a lot of spurious
  3321. complaints that are best ignored.  For this reason, PCQ Pascal
  3322. automatically aborts after four errors (I used to use five, but
  3323. apparently the first error was scrolling off of normal screens).
  3324.  
  3325. If you specified the "-q" Quiet command line option, the error
  3326. reports will have a much more regular form, which is:
  3327.  
  3328. "source file name" At ##,## : Error Text
  3329.  
  3330. The quotes, colon, and the word "At" are all literal.  The first
  3331. ## is the line, and the second is the column.  This format is
  3332. designed to make automated compilation routines easier to develop.
  3333.  
  3334.  
  3335.  
  3336.  
  3337.  
  3338. ===================================================================
  3339.  
  3340.                              Sources
  3341.  
  3342. ===================================================================
  3343.  
  3344. I wrote PCQ Pascal as a learning experience, and it case you're
  3345. wondering I sure learned a lot.  Where did I go for information?
  3346. First, let's look at information specifically about the Amiga.
  3347.  
  3348. Amiga 1.3 Native Developer's Update.  This is a package of four
  3349. disks distributed by Commodore (CATS, specifically).  It has the
  3350. complete C and assembly language include libraries, Amiga.lib,
  3351. ALink, and all sorts of other things.  Perhaps more importantly,
  3352. it also has the Amiga Autodocs, a set of documentation files that
  3353. explain each and every function available in the standard Amiga
  3354. libraries and devices.  It explains each one individually,
  3355. however, so you still need a more general source.  For $20 U.S.,
  3356. however, these disks are a bargain.  The 2.0 update should be out
  3357. eventually, but as I write this it's still unavailable, so you
  3358. should send $20 and ask for the 1.3 update from:
  3359.  
  3360.         C.A.T.S
  3361.         1200 Wilson Drive
  3362.         West Chester, PA 19380
  3363.  
  3364.  
  3365. Amiga ROM Kernel Manuals.  This is the official set of books for
  3366. Amiga programming, and if you don't have them you are handicapped.
  3367. The last version I have is from AmigaOS version 1.1 so I'm not
  3368. sure how they are organized these days, but you should definitely
  3369. get the one that explains Intuition, and if you can still afford
  3370. it, the one that explains Libraries and Devices.  They are big and
  3371. very expensive, but it's hard to get by without them.  Some folks,
  3372. by the way, will also tell you that they are mistake-ridden and
  3373. difficult to understand, but I found them to be very accurate and
  3374. clear.  I think some programmers like to blame their lack of
  3375. understanding on others....
  3376.  
  3377. Anders Bjerin's C manual.  I've never looked at this, so I have no
  3378. idea of what it covers.  It covers lots of Intuition and Graphics
  3379. topics, and the C slant shouldn't be too much of a problem.  It's
  3380. available on Fred Fish disks 456 & 457, and unpacks to four full
  3381. disks of documentation.
  3382.  
  3383.  
  3384. As far as information about compilers in particular, I referred to
  3385. the following sources:
  3386.  
  3387. PDC, a freely distributable C compiler supported by Jeff Lydiatt.
  3388. This is a very good program, although it has been eclipsed
  3389. recently by DICE, GCC, and other really good C compilers.  I
  3390. learned, and used, a lot about activation frames from PDC's
  3391. output, although PDC's source code remains a mystery.
  3392.  
  3393. Pascal-S source code.  This is a small demonstration of a Pascal
  3394. p-code compiler produced years ago at Wirth's place, ETH Zurich.
  3395. It can answer some questions, but isn't a really good example of
  3396. programming style.
  3397.  
  3398. Small-C source code.  Small-C is another freely distributable C
  3399. compiler, originally described in Dr. Dobb's Journal years ago.
  3400. It is not very powerful, but the simplicity of the source code
  3401. makes it a very practical reference.  It is one of the compilers
  3402. used to bootstrap PCQ.
  3403.  
  3404. Brinch Hansen on Pascal Compilers, by Per Brinch Hansen.  This
  3405. book was of some use, which is more than I can say about the other
  3406. half dozen I read while writing this.  From this book I mainly
  3407. learned about all the things I was doing wrong.  Great.
  3408.  
  3409. The Toy Compiler series in Amiga Transactor, written by Chris
  3410. Gray.  This series is very informative, and is written by the
  3411. author of Draco.  Gray also writes compilers for a living, so he
  3412. actually knows what he's talking about.  Unfortunately this series
  3413. is hard to find, because the Transactor is out of business.  Ask
  3414. around, though - it's worth it.
  3415.  
  3416. Compilers: Principles, Techniques and Tools, by Aho, Sethi and
  3417. Ullman.  This is the big book, the so-called Dragon book, the last
  3418. word on compiler writing.  If you want to know about it, it's in
  3419. there, but you had better have a pretty decent math background.
  3420. Although it was a textbook for a class I took, I have never read
  3421. more than a few pages of it.
  3422.  
  3423.  
  3424.  
  3425. ===================================================================
  3426.  
  3427.                     Improvements On The Burner
  3428.  
  3429. ===================================================================
  3430.  
  3431. I've been using 1.2 for several months before I issued it, so I'm
  3432. relatively confident of its quality.  Nonetheless, it's such a
  3433. major change that I expect there will be problems.  Therefore my
  3434. first priority, as always, will be bug fixes.
  3435.  
  3436. Next comes optional C calling conventions, integrated peephole
  3437. optimizing, and possibly IEEE single precision reals.  That's all
  3438. easy enough.
  3439.  
  3440. Version 1.3 will be a compatibility release.  It will include
  3441. Turbo-style strings, function return values, double precision
  3442. reals, and Turbo types: Word, LongInt, ShortInt, etc.  Address
  3443. will become Pointer, Integer will become LongInt, Short will
  3444. become Integer, Exit will become Halt, etc.  I may even implement
  3445. Unit syntax.
  3446.  
  3447. The other area I'd like to explore is debuggers, preferably source
  3448. level.  I've been looking for the source code to one of those
  3449. monitor programs, but have yet to find it.
  3450.  
  3451.  
  3452. ===================================================================
  3453.  
  3454.                           Update History
  3455.  
  3456. ===================================================================
  3457.  
  3458. Version 1.2a (June 8, 1991)
  3459.  
  3460. Fixed several bugs:
  3461.   o   The XOR operator would produce illegal assembly commands.
  3462.   o   Some floating point comparisons would produce incorrect
  3463.       results.
  3464.   o   The $A assembly directive now works anywhere in the code,
  3465.       not just in procedures and functions.
  3466.   o   The compiler used to accept unknown identifiers in typed
  3467.       constants (as operands of the @ operator).
  3468.   o   The INC and DEC statements were not handling Inc(var1,var2)
  3469.       forms correctly.
  3470.  
  3471. Version 1.2 (April 18, 1991)
  3472.  
  3473.     Fixed strlen and CreateTask() to work with 32-bit memory.
  3474.     Re-wrote the expression parsing and code generating routines
  3475. completely.  The routines now use registers much more effectively,
  3476. and provide a good base for the separate peephole optimizer.
  3477.     Added a few Turbo Pascal features:  you can now use typecasts
  3478. anywhere, even in address calculations.  Thus you can now write
  3479. something like RecordType(Pointer^).Field, which in version 1.1
  3480. was illegal.
  3481.     Changed the FOR statement significantly in order to make it
  3482. more efficient, and more like Turbo.  It boils down to two
  3483. differences:  FOR loops no longer run a minimum of once (e.g for i
  3484. := 1 to 0 do ...  will execute zero times), and the BY clause is
  3485. gone.
  3486.     Added short circuit evaluations, automatic floating point
  3487. conversions, Heap functions, Reset and Rewrite.
  3488.     You can now use any standard functions or operators in
  3489. constant expressions.
  3490.     Changed the Read routines to comply with Standard Pascal and
  3491. Turbo, in that any white space is skipped before reading integers
  3492. and reals.  It used to stop at EOLNs.
  3493.  
  3494.  
  3495. Version 1.1d, May 6, 1990:
  3496.  
  3497.     I've begun accumulating small changes under a new version
  3498. number purely for aesthetics.  The first difference is that the
  3499. compiler now creates a SECTION for data only if it has to.  That
  3500. sounds like an efficiency issue, but actually it wasn't creating a
  3501. SECTION at all if it was compiling an External unit.
  3502.     When StdOut is a file, the compiler no longer writes the line
  3503. numbers and all that stuff.  I have also made what I hope is the
  3504. last fix to the real number reading routines.
  3505.     The routines that compares include file names to the list of
  3506. previously included files is now case-insensitive.  I can't
  3507. imagine why it wasn't before.
  3508.  
  3509. Version 1.1c, April 6, 1990:
  3510.  
  3511.     I should have guessed that the problem recognizing the sign of
  3512. small real numbers on output would have a symmetric problem for
  3513. input.  It did, and now it doesn't.  I also fixed the problem with
  3514. signs on real constants.  I also added the exp() and ln()
  3515. functions recently sent to me by Martin Combs.  To avoid inflation
  3516. of version numbers, I've changed the date but kept the same
  3517. version.
  3518.     I've been thinking about adding peephole optimization to the
  3519. process, and rather than doing it the right way I've been playing
  3520. with a separate program.  To make that easier, I've removed short
  3521. branches from the code generated.  A68k adds them where necessary
  3522. anyway.
  3523.  
  3524. Version 1.1c, March 3, 1990:
  3525.  
  3526.     The only changes to the compiler are the new standard
  3527. functions.  The more significant changes were in the runtime
  3528. library.  First, I replaced the sin() and cos() functions based on
  3529. suggestions by Martin Combs - the result is that the results are
  3530. accurate to about 3 digits, and only slightly slower.  Martin was
  3531. kind enough to send along a very useful set of routines, which
  3532. also included the tan() and arctan() functions.  I also fixed the
  3533. routine that writes real numbers, so values between -1.0 and 0.0
  3534. now include the minus sign.
  3535.  
  3536. Version 1.1b, February 6, 1990:
  3537.  
  3538.     This program is over a year old.
  3539.     Added the Sqr() function.  Sqr(n) is the same as n * n, but
  3540. marginally faster and smaller.  Also, the compiler used to
  3541. generate lots of errors when an include file was missing.  Now it
  3542. skips the rest of the comment, like it should.
  3543.     Apparently floating point constants didn't used to work.  Why
  3544. am I always the last to know?  I also added the Sin() and Cos()
  3545. functions, based on an aside during a lecture on an entirely
  3546. different topic.
  3547.     Later I added the sqrt() function, using Newton's method.
  3548.  
  3549. Version 1.1a, January 20, 1990:
  3550.  
  3551.     Fixed a bug in the WriteArb routine that manifested itself
  3552. whenever you wrote to a 'File of Something'.
  3553.     Fixed a bug left in the floating point math library.  It seems
  3554. that it had not been updated for the all the 1.1 changes, so
  3555. during linking it required objects that aren't around anymore.
  3556. Since floating point math is now handled by the compiler, I hadn't
  3557. noticed it before.
  3558.  
  3559. Version 1.1, December 1, 1989:
  3560.  
  3561.     This version is completely re-written, and has far too many
  3562. changes to list them individually here.  The main changes are the
  3563. with statement, the new IO system, a completely redesigned symbol
  3564. table, nested procedures, and several new arithmetic operators.
  3565. In order to help port programs from Turbo Pascal and C, I added
  3566. typed constants, the Goto statement, and the normal syntax for
  3567. multi- dimensional arrays.
  3568.  
  3569. Version 1.0c, May 21, 1989:
  3570.  
  3571.     I changed the input routines around a bit, using DOS files
  3572. rather than PCQ files.  I buffered the input, and made the
  3573. structure more flexible so I could nest includes.  Rather than
  3574. make up some IfNDef directive, I decided to keep track of the file
  3575. names included and skip the ones already done.  Buffering the
  3576. input cut compile times in half.  I would not have guessed
  3577. buffering would be that significant, and I suppose I should
  3578. rethink PCQ input/output in light of this.
  3579.     I added code to check for the CTRL-C, so you can break out
  3580. early but cleanly.  The Ports.i include file had a couple of
  3581. errors, which I fixed, and I also fixed the routine that opens a
  3582. console for programs that need one.  It used to have problems when
  3583. there were several arguments in the first write().
  3584.     I added the SizeOf() function, floating point math, and the
  3585. standard functions related to floating point math.
  3586.     There were several minor problems in the include files which I
  3587. found when I got the 1.3 includes, the first official set I've had
  3588. since 1.0.
  3589.     I relaxed the AND, OR and NOT syntax to allow any ordinal
  3590. type.  This allows you to get bitwise operations on integers and
  3591. whatever.  I also added a standard function called Bit(),
  3592. described above.  These are all temporary until I can get sets
  3593. into the language.
  3594.     I finally added string indexing.  In doing so I found a bug in
  3595. the addressing routine selector(), so I rewrote it to be more
  3596. sensible.  I think it also produces larger code, but I'm not too
  3597. worried because I'm going to add expression trees soon anyway.
  3598.  
  3599. Version 1.0b, April 17, 1989:
  3600.  
  3601.     I fixed a bug in the way complex structures were compared.  It
  3602. seems that one too many bytes were considered, so quite often the
  3603. comparison would fail.
  3604.  
  3605. Version 1.0a, April 8, 1989:
  3606.  
  3607.     This version added 32 bit math, and fixed the case statement.
  3608. The math part was just a matter of getting the proper assembly
  3609. source, but I changed the case statement completely.  Version 1.0
  3610. of the compiler produced a table that was searched sequentially
  3611. for the appropriate value, which if found was matched up with an
  3612. address.  I thought all compilers did this, but when debugging a
  3613. Turbo Pascal program at work I found that it just did a bunch of
  3614. comparisons before each statement, as if it were doing a series of
  3615. optimized if statements.  I had thought of this and rejected it as
  3616. being too simplistic, but if it's good enough for Turbo it's good
  3617. enough for me.
  3618.     The next thing I changed in this release was the startup code.
  3619. You can now run PCQ Pascal programs from the Workbench.  This was
  3620. just a matter of taking care of the Workbench message, but I also
  3621. fooled around with standard input and output.  If you try to read
  3622. or write to standard in or out from a program launched from the
  3623. Workbench, the run time code will open a window for you.
  3624.     I also fixed one bug that I found:  an array index that was
  3625. not a numeric type had its type confused.  Nevermore.
  3626.  
  3627. Version 1.0, February 1, 1989
  3628.  
  3629.     Original release.
  3630.  
  3631.  
  3632.  
  3633. ===================================================================
  3634.  
  3635.                Other Notes, Copyright & My Address
  3636.  
  3637. ===================================================================
  3638.  
  3639. This documentation, the source code for the compiler, the compiler
  3640. itself, the source code for the run time library, and the run time
  3641. library itself, are all (ahem):
  3642.  
  3643.                 Copyright (c) 1989 Patrick Quaid.
  3644.  
  3645. I will allow the package to be freely distributed, as long as all
  3646. the files in the archive, with the possible exception of the
  3647. assembler and linker (please include them if at all possible), are
  3648. included and unchanged.  Of course no one can make any real money
  3649. for distributing this program.  It may only be distributed on disk
  3650. collections where a reasonable fee is charged for the disk itself.
  3651. A reasonable fee is defined here as the greater of $10 per disk,
  3652. or whatever Fred Fish is currently charging (about six dollars as
  3653. I write this).
  3654.  
  3655. Feel free to mess around with the compiler source code.  If you
  3656. make any substantial improvements, I would appreciate a copy of
  3657. them so that they can be incorporated into the next version if
  3658. appropriate.  I would especially like to see any efforts toward
  3659. creating integrated environments through ARexx or whatever.
  3660.  
  3661. This is not a shareware package.  Feel no guilt about using it
  3662. without paying for it.  The one payment I would really appreciate
  3663. is if you could let me know about bugs you discover (not
  3664. unimplemented features- I know about them.  I'm not trying to
  3665. write the end-all greatest compiler, but I do want it to be
  3666. correct).  If you have an overwhelming urge to give money away,
  3667. please send a donation to Charlie Gibbs, who wrote the assembler,
  3668. and the Software Distillery, who wrote the linker.
  3669.  
  3670. If you would like me to send you the latest version of the
  3671. compiler, keep the following in mind.  Disk mailers cost me about
  3672. 50 cents, postage costs me 75 cents, and disks cost about a buck.
  3673. Therefore I would consider anything over $2.25 to be adequate to
  3674. cover my costs, and I don't want anything more.  If getting
  3675. American dollars is too difficult or illegal, skip it.  It's not
  3676. that important.
  3677.  
  3678. Any questions, comments, or whatever can be addressed to:
  3679.  
  3680.       Pat Quaid
  3681.       8320 E. Redwing
  3682.       Scottsdale, AZ 85250
  3683.  
  3684.       Telephone: (602) 967-3356
  3685.       FidoNet: Patrick Quaid @ 1:114/52
  3686.  
  3687. You are much more likely to be able to contact me by mail than by
  3688. phone, but I certainly don't mind if you try.  Enjoy the compiler.
  3689. If you have any complaints, remember what you paid for it.
  3690.